IronPython ‘Тип IEnumerable`1[TSource] содержит общие параметры’ при использовании расширений Linq в структурах IEnumerable

#c# #ironpython

#c# #ironpython

Вопрос:

Я пытаюсь добавить поддержку сценариев Python в существующую библиотеку C #, используя IronPython. Однако при попытке использовать методы расширения Linq в одной из моих структур, которая является IEnumerable<T>, я получаю исключение System.Collections.Generic.IEnumerable`1[TSource] contains generic parameters' , тогда как когда я меняю тип на класс, он работает, как ожидалось.

Вот некоторый переработанный код, который отображает то же поведение. Как упоминалось, изменение A на класс решает проблему, но это привело бы к ненужной генерации мусора в моем реальном коде проекта, поэтому я бы предпочел не прибегать к этому. Я использую IronPython 2.7.9 от Nuget.

 using IronPython.Hosting;
using Microsoft.Scripting;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace IronPython279
{
    public struct A : IEnumerable<int>
    {
        public IEnumerator<int> GetEnumerator() => new List<int>(new[] { 1, 2, 3 }).GetEnumerator();
        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }

    class Program
    {
        static void Main(string[] args)
        {
            var engine = Python.CreateEngine();
            var scope = engine.CreateScope();

            var sourceCode = new StringBuilder();
            sourceCode.AppendLine("import clr");
            sourceCode.AppendLine($"clr.AddReference("{nameof(System)}.Core")");
            sourceCode.AppendLine($"clr.AddReference("{nameof(IronPython279)}")");
            sourceCode.AppendLine($"import {nameof(System)}");
            sourceCode.AppendLine($"import {nameof(IronPython279)}");
            sourceCode.AppendLine($"from {nameof(IronPython279)} import {nameof(A)}");
            sourceCode.AppendLine($"clr.ImportExtensions({nameof(System)}.{nameof(System.Linq)})");
            sourceCode.AppendLine($"a = {nameof(A)}()");
            sourceCode.AppendLine($"b = a.{nameof(System.Linq.Enumerable.First)}()");
            var source = engine.CreateScriptSourceFromString(sourceCode.ToString(), SourceCodeKind.Statements);
            source.Execute(scope);
        }
    }
}
  

Что означает эта ошибка (в ней указано что-то, что является правдой, но не почему это проблема) и существуют ли какие-либо другие обходные пути, помимо перехода на класс?

Комментарии:

1. Примечание сбоку: » Как упоминалось, изменение A на класс решает проблему, но это привело бы к ненужной генерации мусора в моем реальном коде проекта » Этот аргумент спорный, поскольку передача (или попытка передать) структуры как IEnumerable<T> в любом случае потребовала бы упаковки…

2. @elgonzo Хотя в этом случае вы справедливо указываете, реальная структура обладает другими свойствами и может быть просто создана для них, что означает множество случаев, когда упаковка не выполняется.