Skip to content

pythonnet 3.0 breaks access to methods whos signature returns an interface but clients want to use the concrete type #1914

Closed as not planned

Description

@koubaa

Environment

  • Pythonnet version: 3.0+
  • Python version: any
  • Operating System: any
  • .NET Runtime: any

tldr;
#1240 changes the behavior of pythonnet to wrap only the interface methods/members of objects returned by a .NET method whose method declaration states that it returns an interface. Prior to this change, the python object that pythonnet created for the return object wrapped the returned object instance, but did not necessarily implement the interface. The prior behavior was useful for idiomatic C# patterns like the factory pattern.

This was discussed on the mailing list and I wanted to file an issue here.

Apparently, the change was also reverted in the QuantConnect fork.

My preferred fix, for what its worth, is option 4 (from the list of options mentioned by Victor in that thread):

IronPython apparently allows explicit interface implementations to be called (instead of returning interface-wrapped instances), if there’s no conflict with regular methods. Perhaps we should consider this as an option.

Activity

  1. changed the title [-]pythonnet 3.0 breaks idiomatic C# patterns[/-] [+]pythonnet 3.0 breaks access to methods whos signature returns an interface but clients want to use the concrete type[/+] on Aug 15, 2022
  2. lostmsu commented on Aug 16, 2022

    @lostmsu
    Member

    What you are proposing is not an idiomatic C# pattern. In C# if you get an instance of interface returned from a method, you have to cast it to a specific type before you can call public methods that are not part of the interface.

  3. koubaa commented on Aug 17, 2022

    @koubaa
    ContributorAuthor

    @lostmsu fair point. It's idiomatic for dynamically typed languages, which C# is not. I do still think the current behavior is problematic.

  4. filmor commented on Aug 17, 2022

    @filmor
    Member

    Inhowfar? It's exactly like it is in C#: You ask for an ISomething and you get one back. If you wanted the behaviour you are asking for, you'd use dynamic or cast explicitly.I don't think we support either of this nicely right now, but both options would be preferable, IMO.

  5. koubaa commented on Aug 18, 2022

    @koubaa
    ContributorAuthor

    @filmor dynamically typed languages don't have return types, so what you get back is always some concrete implementation.

    Anyways - I prefer not to get into a philosophical debate here, sorry for inviting one by using the term idiomatic earlier in the thread. This is mostly a practical problem when interfacing a C# library with python using pythonnet without having to rewrite the C# library (in many cases the development of the python interface and the C# library may be handled by separate teams or organizations).

  6. lostmsu commented on Aug 21, 2022

    @lostmsu
    Member

    Logically, you can think of the return value in this case the same way as a super object, e.g. super(IInterface, obj) except you can also unwrap the result and get obj out of it. The super object does not permit access to obj members outside of IInterface.

  7. filmor commented on Sep 14, 2022

    @filmor
    Member

    I think we agree from the maintainer side that we are not going to change this behaviour. Adding an explicit cast (clr.cast[SomeType](result) or a "make this dynamic" (clr.dynamic(result)) would definitely be an option, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions