Out of curiosity I decided to try decompiling my project's code. I took the Assembly .dll file and used ILSpy to decompile it. It seems to be working correctly, except for IEnumerator<> methods.
IEnumerator sP()
{
for (int i = 0; i < maxEnemies; i++)
{
var p = Porczaks[Random.Range(0, Porczaks.Length)];
Instantiate(p, new Vector3(Random.Range(245, 360), 16.8f, Random.Range(292, 366)), Quaternion.Euler(0f, Random.Range(0f, 359f), 0f));
yield return new WaitForEndOfFrame();
}
}
... is for example being decoded into this:
[DebuggerHidden]
private IEnumerator sP()
{
WaveManager.<sP>c__Iterator7 <sP>c__Iterator = new WaveManager.<sP>c__Iterator7();
<sP>c__Iterator.<>f__this = this;
return <sP>c__Iterator;
}
Is there any way to accurately decompile that IEnumerator?
EDIT: I decompiled the same assembly using the dotPeek decompiler, and it created way more code. Though I'm still not sure if variables can have such names in .net:
// Method sP with token 060000AB
[/*Attribute with token 0C000051*/DebuggerHidden]
private IEnumerator sP()
{
WaveManager.\u003CsP\u003Ec__Iterator7 sPCIterator7 = new WaveManager.\u003CsP\u003Ec__Iterator7();
sPCIterator7.\u003C\u003Ef__this = this;
return (IEnumerator) sPCIterator7;
}
// Type <sP>c__Iterator7 with token 02000031
[/*Attribute with token 0C000026*/CompilerGenerated]
private sealed class \u003CsP\u003Ec__Iterator7 : IEnumerator<object>, IEnumerator, IDisposable
{
// Field <i>__0 with token 040000C7
internal int \u003Ci\u003E__0;
// Field <p>__1 with token 040000C8
internal GameObject \u003Cp\u003E__1;
// Field $PC with token 040000C9
internal int \u0024PC;
// Field $current with token 040000CA
internal object \u0024current;
// Field <>f__this with token 040000CB
internal WaveManager \u003C\u003Ef__this;
// Property System.Collections.Generic.IEnumerator<object>.Current with token 17000017
object IEnumerator<object>.System\u002ECollections\u002EGeneric\u002EIEnumerator\u003Cobject\u003E\u002ECurrent
{
// Method System.Collections.Generic.IEnumerator<object>.get_Current with token 060000EA
[/*Attribute with token 0C00006E*/DebuggerHidden] get
{
return this.\u0024current;
}
}
// Property System.Collections.IEnumerator.Current with token 17000018
object IEnumerator.Current
{
// Method System.Collections.IEnumerator.get_Current with token 060000EB
[/*Attribute with token 0C00006F*/DebuggerHidden] get
{
return this.\u0024current;
}
}
// Method .ctor with token 060000E9
public \u003CsP\u003Ec__Iterator7()
{
base.\u002Ector();
}
// Method MoveNext with token 060000EC
public bool MoveNext()
{
uint num = (uint) this.\u0024PC;
this.\u0024PC = -1;
switch (num)
{
case 0:
this.\u003Ci\u003E__0 = 0;
break;
case 1:
this.\u003Ci\u003E__0 = this.\u003Ci\u003E__0 + 1;
break;
default:
return false;
}
if (this.\u003Ci\u003E__0 < this.\u003C\u003Ef__this.maxEnemies)
{
this.\u003Cp\u003E__1 = this.\u003C\u003Ef__this.Porczaks[UnityEngine.Random.Range(0, this.\u003C\u003Ef__this.Porczaks.Length)];
UnityEngine.Object.Instantiate((UnityEngine.Object) this.\u003Cp\u003E__1, new Vector3((float) UnityEngine.Random.Range(245, 360), 16.8f, (float) UnityEngine.Random.Range(292, 366)), Quaternion.Euler(0.0f, UnityEngine.Random.Range(0.0f, 359f), 0.0f));
this.\u0024current = (object) new WaitForEndOfFrame();
this.\u0024PC = 1;
return true;
}
this.\u0024PC = -1;
goto default;
}
// Method Dispose with token 060000ED
[/*Attribute with token 0C000070*/DebuggerHidden]
public void Dispose()
{
this.\u0024PC = -1;
}
// Method Reset with token 060000EE
[/*Attribute with token 0C000071*/DebuggerHidden]
public void Reset()
{
throw new NotSupportedException();
}
}
Seems dotPeek didn't process < and > correctly, but is this code worth anything?
You really see the boilerplate code the compiler generates to replace the yield return statement. And yes it is indeed a state machine.
Normally a decompiler should be able to recognize the compiler generated boilerplate code and replace it with the correct C# statement. That recognition, however, is done by pattern matching, i.e. the boilerplate code is expected to be structured in a very specific way. If the compiler produces equivalent code but with different structure (e.g. because of compiler upgrade, optimizations, etc.) then the decompiler fails to match the pattern and recognize the yield statement.
What you should do is submit a bug report to the decompiler teams so that this gets fixed and you don't have to rename stuff manually. Have you tried JustDecompile on that assembly? Does it fail, too? If so, you could post this in the Telerik forums and we'll take care of it.
On a side note, what compiler did you use?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With