Что может вызвать это ExecutionEngineException?

Я пытаюсь использовать Reflection.Emit для генерации класса-оболочки в динамической сборке. Автоматическое создание обертки является частью новой библиотеки с открытым исходным кодом, которую я пишу под названием "GoInterfaces".

Класс-обертка реализует IEnumerable<string> и обертывания List<string>, В терминах C# все, что он делает, это:

class List1_7931B0B4_79328AA0 : IEnumerable<string>
{
    private readonly List<string> _obj;

    public List1_7931B0B4_79328AA0(List<string> obj)
    {
        this._obj = obj;
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this._obj.GetEnumerator();
    }
    public sealed IEnumerator<string> GetEnumerator()
    {
        return this._obj.GetEnumerator();
    }
}

Однако, когда я пытаюсь вызвать метод GetEnumerator() в моем классе-обертке, я получаю исключение ExecutionEngineException. Поэтому я сохранил мою динамическую сборку в DLL и использовал на ней ildasm. Что-то не так с приведенным ниже кодом?

.class public auto ansi sealed List`1_7931B0B4_79328AA0
    extends [mscorlib]System.Object
    implements [mscorlib]System.Collections.Generic.IEnumerable`1<string>, 
               [Loyc.Runtime]Loyc.Runtime.IGoInterfaceWrapper
{
    .field private initonly class 
        [mscorlib]System.Collections.Generic.List`1<string> _obj

    .method public hidebysig virtual final instance 
            class [mscorlib]System.Collections.Generic.IEnumerator`1<string> 
            GetEnumerator() cil managed
    {
        // Code size       12 (0xc)
        .maxstack  1
        IL_0000:  ldarg.0
        IL_0001:  ldfld      class [mscorlib]System.Collections.Generic.List`1<string> List`1_7931B0B4_79328AA0::_obj
        IL_0006:  call       instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<string>::GetEnumerator()
        IL_000b:  ret
    } // end of method List`1_7931B0B4_79328AA0::GetEnumerator


    .method public hidebysig virtual final instance 
            class [mscorlib]System.Collections.IEnumerator 
            System.Collections.IEnumerable.GetEnumerator() cil managed
    {
        .override [mscorlib]System.Collections.IEnumerable::GetEnumerator
        // Code size       12 (0xc)
        .maxstack  1
        IL_0000:  ldarg.0
        IL_0001:  ldfld      class [mscorlib]System.Collections.Generic.List`1<string> List`1_7931B0B4_79328AA0::_obj
        IL_0006:  call       instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<string>::GetEnumerator()
        IL_000b:  ret
    } // end of method List`1_7931B0B4_79328AA0::System.Collections.IEnumerable.GetEnumerator
    ...

У меня есть набор тестов, который охватывает все виды различных вещей, в том числе интерфейсы, полученные из других интерфейсов, и несколько методов интерфейса с идентичными сигнатурами. Это только когда я пытаюсь завернуть IEnumerable<T> что эта проблема возникает. Я был бы рад выслать исходный код (2 *.cs файлы, без зависимостей), если кто-то захочет.

1 ответ

Решение

List<T> на самом деле имеет 3 GetEnumerator() методы; это явно реализует IEnumerable.GetEnumerator() а также IEnumerable<T>.GetEnumerator(), но это также имеет общественное GetEnumerator() метод, возвращающий List<T>.Enumerator экземпляр, который является типом значения. Ваш код вызывает этот метод, и поэтому вам нужно вставить box код операции между call и ret,

Для дальнейшего использования это довольно легко выяснить, если вы просто скомпилируете свой пример кода C#, посмотрите его в Reflector и сравните с вашим собственным IL.

Другая проблема с вашим IL заключается в том, что ваша явная реализация интерфейса не должна быть публичной, она должна быть закрытой. Есть также несколько других незначительных различий, но я не думаю, что любое из них могло бы вызвать исключение.

Другие вопросы по тегам