question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

.NET objects returned as interface 'lose' their most-derived type identity

See original GitHub issue

Environment

  • Pythonnet version: 3.0.1
  • Python version: 3.10.11
  • Operating System: Windows 11
  • .NET Runtime: .NET Framework 4.8.9167.0

Details

  • Describe what you were trying to get done. Return an interface derived from the one declared as a method or property’s return type and be able to do RTTI to detect the type of derived interface returned. Do the same with a heterogeneous collection where the collection’s type is declared as a collection of BaseInterface but the members are implementations of DerivedInterfaces.

  • What commands did you run to trigger this issue? Given some C# library code:

public interface IBaseInterface { }

public interface IDerivedInterfaceX : IBaseInterface  { }

public interface IDerivedInterfaceY : IBaseInterface  { }

public class ConcreteX : IDerivedInterfaceX { }

public class ConcreteY : IDerivedInterfaceY { }

public class Factory
{
    public IBaseInterface PolymorphicObject => new ConcreteX();
    public IEnumerable<IBaseInterface> HeterogenousPolymorphicCollection=> new IBaseInterface[] { new ConcreteY(), new ConcreteX() };
}

Python client code behaves differently than C# client code:

static void Main(string[] args)
{
    Factory f = new();
    IBaseInterface obj = f.PolymorphicObject;
    bool isDerived = obj is IDerivedInterfaceX; // true

    foreach (IBaseInterface obj2 in f.HeterogenousPolymorphicCollection)
    {
        bool isDerivedX = obj2 is IDerivedInterfaceX; // false then true
        bool isDerivedY = obj2 is IDerivedInterfaceY; // true then false
    }
}
f = Factory()

obj = f.PolymorphicObject  # Type is IBaseInterface FOREVER
isDerived = isinstance(obj, IDerivedInterfaceX)  # Always False
isSubclass = issubclass(type(obj), IDerivedInterfaceX)  # Always False

for obj2 in f.HeterogenousPolymorphicCollection:  # Type is IBaseInterface FOREVER
    isDerivedX = isinstance(obj2, IDerivedInterfaceX)  # ALWAYS FALSE
    isDerivedY = isinstance(obj2, IDerivedInterfaceY)  # ALWAYS FALSE

We know it’s possible to “cheat” by testing obj.__implementation__'s type but we’d rather keep everything as interfacey as possible 😃

We know the official solution is to attempt to upcast the returned objects but of course this will throw an exception if it’s not possible – we’d like to examine the type returned to ensure no exception before we upcast.

Is there a nice, pretty solution?

Issue Analytics

  • State:open
  • Created a month ago
  • Comments:8 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
filmorcommented, Aug 9, 2023

Yeah, I think I’ll prepare a PR for adding functions for this. We should have probably added these right when the change in behaviour happened.

1reaction
filmorcommented, Aug 7, 2023

We can’t adjust isinstance and issubclass (which is correct anyhow, one would need to adjust type(obj)) without also going back to the “old” behaviour of trying to resolve all fields, properties and methods dynamically. Otherwise, if isinstance(obj, SomeClass): obj.PropertyDefinedInSomeClass would fail.

Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - Cannot convert type 'Task<Derived>' to 'Task<Interface>'
I have the following function with a delegate parameter that accepts a type of one interface and returns a task of another. public...
Read more >
How to serialize properties of derived classes with System. ...
In this article. Serialize properties of derived classes; Polymorphic type discriminators; Configure polymorphism with the contract model ...
Read more >
Use composition and inheritance for DTOs
One reason not to use concrete inheritance among DTOs is that certain tools will happily map them to the wrong types.
Read more >
Interfaces in C# - What they are, how to use them ... - YouTube
Well, you watch this video and learn how to ask the right question the ... Note about items in the List of type...
Read more >
Covariant Return Types - Draft Specification · Issue #2844
Abstract This is a draft proposed specification for covariant return types in C#. Our intent is to permit the override of a method...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found