В настоящее время я работаю над добавлением новой функции в существующий API.
Я определяю новый атрибут, чтобы всякий раз, когда тип отмечен этим указанным атрибутом c, я хотел бы l oop через некоторый список.
Допустим, у меня есть следующий код:
public class TestClass
{
List<int> Numbers = new List<int> { 1, 2, 3, 4, 5 };
public void Sum()
{
int total = 0;
foreach (int i in Numbers)
{
total += i;
}
}
}
Декомпилированный C# код для метода Sum()
-
public class TestClass
{
public void Sum()
{
int num = 0;
List<int>.Enumerator enumerator = Numbers.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
int current = enumerator.Current;
num += current;
}
}
finally
{
((IDisposable)enumerator).Dispose();
}
}
}
и декомпилированный код IL:
.method public hidebysig
instance void Sum () cil managed
{
// Method begins at RVA 0x2050
// Code size 59 (0x3b)
.maxstack 2
.locals init (
[0] int32,
[1] valuetype [System.Private.CoreLib]System.Collections.Generic.List`1/Enumerator<int32>,
[2] int32
)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: nop
IL_0004: ldarg.0
IL_0005: ldfld class [System.Private.CoreLib]System.Collections.Generic.List`1<int32> TestClass::Numbers
IL_000a: callvirt instance valuetype [System.Private.CoreLib]System.Collections.Generic.List`1/Enumerator<!0> class [System.Private.CoreLib]System.Collections.Generic.List`1<int32>::GetEnumerator()
IL_000f: stloc.1
.try
{
// sequence point: hidden
IL_0010: br.s IL_0020
// loop start (head: IL_0020)
IL_0012: ldloca.s 1
IL_0014: call instance !0 valuetype [System.Private.CoreLib]System.Collections.Generic.List`1/Enumerator<int32>::get_Current()
IL_0019: stloc.2
IL_001a: nop
IL_001b: ldloc.0
IL_001c: ldloc.2
IL_001d: add
IL_001e: stloc.0
IL_001f: nop
IL_0020: ldloca.s 1
IL_0022: call instance bool valuetype [System.Private.CoreLib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()
IL_0027: brtrue.s IL_0012
// end loop
IL_0029: leave.s IL_003a
} // end .try
finally
{
// sequence point: hidden
IL_002b: ldloca.s 1
IL_002d: constrained. valuetype [System.Private.CoreLib]System.Collections.Generic.List`1/Enumerator<int32>
IL_0033: callvirt instance void [System.Private.CoreLib]System.IDisposable::Dispose()
IL_0038: nop
IL_0039: endfinally
} // end handler
IL_003a: ret
} // end of method TestClass::Sum
( Декомпилированный код создается с использованием SharpLab.io
.)
Особый интерес представляет инструкция IL_0014
, который вызывает get_Current()
. Соответствующий декомпилированный код C# просто вызывает свойство Current
в перечислителе.
Как вывести эту инструкцию, используя MonoCecil? Это не будет работать, если создать MethodReference
с имя get_Current
, потому что декомпилированный код C# будет тогда get_Current()
, а не Current
.