Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a specific interface on a C# object in IronPython

Tags:

c#

ironpython

I have a C# class that implements 2 IEnumerable interfaces. How can I access either interface from IronPython?

My class:

public class MyClass : IEnumerable<TypeA>, IEnumerable<TypeB>
{
    IEnumerator<TypeA> IEnumerable<TypeA>.GetEnumerator()
    {
        return _lstTypeA.GetEnumerator();
    }

    IEnumerator<TypeB> IEnumerable<TypeB>.GetEnumerator()
    {
        return _lstTypeB.GetEnumerator();
    }
}

I tried the following in Python, but although it runs without errors it does not return any elements from the IEnumerable interface:

x = MyClass()
xA = clr.Convert(x, IEnumerable[TypeA])
for y in xA: print y
like image 467
Han Avatar asked Mar 06 '26 09:03

Han


2 Answers

I don't like your class design. In particular that you implement two different versions of IEnumerable<T> that return different members. Two versions that return the same members is slightly better, but I still don't like that much.

  1. Implementing IEnumerable so it's consistent with both IEnumerable<T>s isn't possible here. In particular that breaks the OfType and Cast linq methods.
  2. You get overload resolution problems almost everywhere. Methods like Select<T>(this IEnumerable<T> ...) don't know which IEnumerable to take.
  3. You can't use foreach on MyClass
  4. If both TypeA and TypeB are reference types the variance of IEnumerable<out T> comes back to bite you. Since both of them offer IEnumerable<T'> for all their common ancestors.
  5. It doesn't interact well with dynamically types languages
  6. A class being a two different collections at the same time rarely makes sense. It usually indicates that something went wrong in the mapping from concepts to classes.
  7. It's confusing and hard to understand. My intuition tells me it's evil and that I should burn it with fire :P

And Probably several more issues I didn't think of yet.


The work around is simple and clean: Have two separate enumerable properties.

public class MyClass
{
  public IEnumerable<TypeA> TypeAs{get{_lstTypeA.Select(x=>x)}};
  public IEnumerable<TypeB> TypeBs{get{_lstTypeB.Select(x=>x)}};
}
like image 100
CodesInChaos Avatar answered Mar 07 '26 23:03

CodesInChaos


You need to call methods and properties as you were using reflection (that is actually what it happens under the hood).

In your case you should do:

x = MyClass()
enumerator = IEnumerable[TypeA].GetEnumerator(x)

then you can loop over enumerator:

for y in enumerator:
   print y
like image 28
digEmAll Avatar answered Mar 07 '26 21:03

digEmAll



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!