Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate over C# Iterator (IEnumerable) in Matlab

Tags:

c#

.net

matlab

I have a C# method that returns very large number of objects. This is to be consumed in Matlab.

namespace MyNameSpace{
    public static class MyClass{
        public static IEnumerable<MyDataObject> GetVeryLargeResponse(){
            while(CheckForSomeFunkyConditionThatsRarelyTrue()){
               yield return GetMyNextDataObject();
            }
            yield break;
        }
    }
}

In Matlab when I make a call

result = MyClass.GetVeryLargeResponse();

I would expect result to be of type IEnumerable<MyDataObject>, so as to be able to get the Enumerator<MyDataObject> by calling result.GetEnumerator().

Where as I'm getting result which is of type MyNameSpace.<GetVeryLargeResponse>d_3 with no GetEnumerator() method available. I do see one of result's Super class being System.Collections.Generic.IEnumerable<MyClass>.

Is there a way I can iterate over this in Matlab or even to 'cast' result to IEnumerable<MyClass> in Matlab.

p.s.

  1. Converting to Array / IList etc is not feasible due to data volume
  2. This is not duplicate of How can I iterate over a C# IEnumerable in Matlab?, as that is dealing with IQueryable specifically.
  3. I'm using Matlab 2010b
like image 436
YetAnotherUser Avatar asked Jul 07 '11 16:07

YetAnotherUser


People also ask

What is iteration in C?

The looping can be defined as repeating the same process multiple times until a specific condition satisfies. It is known as iteration also. There are three types of loops used in the C language.

Does C have iterator?

An iterator is an object that allows you to step through the contents of another object, by providing convenient operations for getting the first element, testing when you are done, and getting the next element if you are not. In C, we try to design iterators to have operations that fit well in the top of a for loop.

How do I iterate through an array in C?

C – Iterate over Array using While Loop To iterate over Array using While Loop, start with index=0, and increment the index until the end of array, and during each iteration inside while loop, access the element using index.


2 Answers

The result does have a GetEnumerator() method - it's just may be implemented with explicit interface implementation.

If Matlab isn't willing to handle that, you could always write your own mapping type and an extension method to make things simpler:

public static class Extensions
{
    public static EnumerableWrapper<T> Wrap<T>(this IEnumerable<T> source)
    {
        return new EnumerableWrapper<T>(source);
    }
}

public class EnumerableWrapper<T> : IEnumerable<T>
{
    private readonly IEnumerable<T> source;

    public EnumerableWrapper(IEnumerable<T> source)
    {
        this.source = source;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return new EnumeratorWrapper<T>(source.GetEnumerator());
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public class EnumeratorWrapper<T> : IEnumerator<T>
{
    private readonly IEnumerator<T> source;

    public EnumeratorWrapper(IEnumerator<T> source)
    {
        this.source = source;
    }

    public T Current { get { return source.Current; } }

    object IEnumerator.Current { get { return Current; } }

    public bool MoveNext()
    {
        return source.MoveNext();
    }

    public void Reset()
    {
        source.Reset();
    }

    public void Dispose()
    {
        source.Dispose();
    }

}

Then try:

result = MyClass.GetVeryLargeResponse().Wrap();

It seems very odd for Matlab not so support this out of the box though...

like image 57
Jon Skeet Avatar answered Sep 30 '22 02:09

Jon Skeet


Consider the following example:

MyClass.cs

namespace MyNameSpace {
    public class Person {
        public string name { get; set; }
        public int age { get; set; }
    }

    public class MyClass {
        private static List<Person> people = new List<Person> {
            new Person {name = "name1", age=10},
            new Person {name = "name2", age=20},
            new Person {name = "name3", age=30},
            new Person {name = "name4", age=40},
            new Person {name = "name5", age=50}
        };

        public static IEnumerable<Person> GetPeople() {
            foreach (var p in people) {
                yield return p;
            }
        }
    }
}

code.m

%# load my assembly
str = 'C:\path\to\MyNameSpace.dll';
NET.addAssembly(str);

obj = MyNameSpace.MyClass.GetPeople();   %# IEnumerable<Person>

%# call ToArray() extension method: this forces immediate query evaluation
NET.addAssembly('System.Core');          %# contains 'System.Linq' namespace
arr = NET.invokeGenericMethod('System.Linq.Enumerable', 'ToArray', ...
    {'MyNameSpace.Person'}, obj);

%# loop through results
for i=1:arr.Length
    fprintf('name=%s, age=%d\n', char(arr(i).name), int32(arr(i).age));
end

The code produces the output:

name=name1, age=10
name=name2, age=20
name=name3, age=30
name=name4, age=40
name=name5, age=50

As you can see, I did convert the returned object as an array Person[] (which I realize you were trying to avoid). The weird thing is if you if we look at the hierarchy of classes:

>> superclasses(obj)
Superclasses for class MyNameSpace.<GetPeople>d__0:
    System.Object
    System.Collections.Generic.IEnumerable<MyNameSpace*Person>
    System.Collections.IEnumerable
    System.Collections.Generic.IEnumerator<MyNameSpace*Person>
    System.IDisposable
    System.Collections.IEnumerator
    handle

you can see the System.Collections.Generic.IEnumerator<Person>, but somehow the object doesn't seem to expose the inherited GetEnumerator method:

>> methods(obj,'-full')

Methods for class MyNameSpace.<GetPeople>d__0:

MyNameSpace.<GetPeople>d__0 obj <GetPeople>d__0(int32 scalar <>1__state)
logical scalar RetVal Equals(MyNameSpace.<GetPeople>d__0 this, System.Object obj)
int32 scalar RetVal GetHashCode(MyNameSpace.<GetPeople>d__0 this)
System.Type RetVal GetType(MyNameSpace.<GetPeople>d__0 this)
System.String RetVal ToString(MyNameSpace.<GetPeople>d__0 this)
event.listener L addlistener(handle sources, char vector eventname, function_handle scalar callback)  % Inherited from handle
event.proplistener L addlistener(handle sources, meta.property properties, char vector eventname, function_handle scalar callback)  % Inherited from handle
event.proplistener L addlistener(handle sources, string propertyname, char vector eventname, function_handle scalar callback)  % Inherited from handle
event.proplistener L addlistener(handle sources, cell propertynames, char vector eventname, function_handle scalar callback)  % Inherited from handle
delete(handle obj)  % Inherited from handle
logical TF eq(A, B)  % Inherited from handle
handle HM findobj(handle H, varargin)  % Inherited from handle
meta.property prop findprop(handle scalar object, string propname)  % Inherited from handle
logical TF ge(A, B)  % Inherited from handle
logical TF gt(A, B)  % Inherited from handle
logical validity isvalid(handle obj)  % Inherited from handle
logical TF le(A, B)  % Inherited from handle
logical TF lt(A, B)  % Inherited from handle
logical TF ne(A, B)  % Inherited from handle
notify(handle sources, string eventname)  % Inherited from handle
notify(handle sources, string eventname, event.EventData scalar eventdata)  % Inherited from handle
like image 45
Amro Avatar answered Sep 30 '22 01:09

Amro