Что может вызвать это 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 заключается в том, что ваша явная реализация интерфейса не должна быть публичной, она должна быть закрытой. Есть также несколько других незначительных различий, но я не думаю, что любое из них могло бы вызвать исключение.