Итерация по C # Итератор (IEnumerable) в Matlab - PullRequest
5 голосов
/ 07 июля 2011

У меня есть метод C #, который возвращает очень большое количество объектов. Это должно быть использовано в Matlab.

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

В Matlab, когда я звоню

result = MyClass.GetVeryLargeResponse();

Я ожидаю, что результат будет иметь тип IEnumerable<MyDataObject>, чтобы можно было получить Enumerator<MyDataObject>, вызвав result.GetEnumerator().

Где, как я получаю result, который имеет тип MyNameSpace.<GetVeryLargeResponse>d_3 без метода GetEnumerator(). Я вижу, что один из суперклассов result является System.Collections.Generic.IEnumerable<MyClass>.

Есть ли способ, по которому я могу повторить это в Matlab или даже «привести» result к IEnumerable<MyClass> в Matlab.

приписка

  1. Преобразование в Array / IList и т. Д. Невозможно из-за объема данных
  2. Это не дубликат Как я могу перебрать C # IEnumerable в Matlab? , так как это имеет дело именно с IQueryable.
  3. Я использую Matlab 2010b

Ответы [ 3 ]

5 голосов
/ 08 июля 2011

Рассмотрим следующий пример:

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

Код производит вывод:

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

Как видите, я преобразовал возвращаемый объект в массив Person[] (которого, как я понимаю, вы пытались избежать).Странная вещь, если вы, если мы посмотрим на иерархию классов:

>> 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

вы можете увидеть System.Collections.Generic.IEnumerator<Person>, но каким-то образом объект, кажется, не предоставляет унаследованный метод GetEnumerator:1018 *

>> 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
5 голосов
/ 07 июля 2011

Результат имеет метод GetEnumerator() - он просто может быть реализован с явной реализацией интерфейса.

Если Matlab не желает обрабатывать это, вы всегда можете написать свойсвой собственный тип отображения и метод расширения, чтобы сделать вещи проще:

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();
    }

}

Затем попробуйте:

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

Кажется очень странным, что Matlab не так поддерживает это из коробки, хотя ...

0 голосов
/ 26 января 2016

Вам нужно использовать явные приведения. Сначала явно приведите экземпляр IEnumerable:

result = MyClass.GetVeryLargeResponse();
resultEnumerable = NET.explicitCast(result,'System.Collections.IEnumerable');

Тогда получите счетчик:

resultEnumerator = resultEnumerable.GetEnumerator();

Затем явно приведем перечислитель:

resultEnumerator = NET.explicitCast(resultEnumerator, 'System.Collections.IEnumerator');

Затем вы можете перебирать коллекцию по желанию:

while (resultEnumerator.MoveNext)
    resultEnumerator.Current
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...