Comments
14 comments
-
The types named like "<>f__AnonymousType0" are the anonymous types that the compiler generates for code such as the following
int[] items = new int[] { 1, 2, 3, 4 };
var result = items.Select(x => new { A = x });
where it needs to generate a class with a property A for holding the result of the select.
If I compile the above code and de-compile using Reflector, with the View/Options/Optimization set to 3.5 I get
int[] items = new int[] { 1, 2, 3, 4 };
var result = from x in items select new { A = x };
but if I set it to 1.0, Reflector no longer tries to get rid of the anonymous types and I see
var result = new int[] { 1, 2, 3, 4 }.Select((CS$<>9__CachedAnonymousMethodDelegate1 != null) ? CS$<>9__CachedAnonymousMethodDelegate1 : (CS$<>9__CachedAnonymousMethodDelegate1 = new Func<int, <>f__AnonymousType0<int>>(MainWindow.<Test>b__0)));
}
If you have the optimization level set to 3.5, then it is a bug if Reflector is not getting rid of the anonymous types. Do you have a reproducible example we can have a look at to debug this?
In your example, the new { stategroup = stategroup, state = state } is the type the compiler is generating as <>f__AnonymousType0 - this instance is then being passed into the Where and the StoryBoard is being pulled out of the state component and returned. -
Here is an example:
bool istrue = (CS$<>9__CachedAnonymousMethodDelegate8 == null) && Enumerable.All<FrameworkElement>(allParents, CS$<>9__CachedAnonymousMethodDelegate8);
[CompilerGenerated]
private static Func<FrameworkElement, bool> CS$<>9__CachedAnonymousMethodDelegate8;
what's the possible original code with lambda expression for above disassembled code? -
Thanks for you information i newly join and your post help me.
-
Somewhere in the updates from version 5.x to 6.x ( I suspect when .NET 4.0 support was added ) the generation of C# for linq, initializers, extensions and anonymous methods has become atrocious.
It is almost making the tool useless as C# language features in our codebase become common place.
For example generator is now displaying direct execution of the static methods instead as an extension.
ie
Real Codeprivate class ReflectorExample { public ReflectorExample() { List<string> aListOfStrings = new List< string >() { "One", "Two", "Three" }; int countOf = aListOfStrings.Where( item => item.Length == 3 ).Count(); } }
Reflected codeprivate class ReflectorExample { [CompilerGenerated] private static Func<string, bool> CS$<>9__CachedAnonymousMethodDelegate4; [CompilerGenerated] private static bool <.ctor>b__3(string item) { return (item.Length == 3); } // Methods public ReflectorExample() { List<string> <>g__initLocal2 = new List<string>(); <>g__initLocal2.Add("One"); <>g__initLocal2.Add("Two"); <>g__initLocal2.Add("Three"); List<string> aListOfStrings = <>g__initLocal2; if (CS$<>9__CachedAnonymousMethodDelegate4 == null) { CS$<>9__CachedAnonymousMethodDelegate4 = new Func<string, bool>(null, (IntPtr) <.ctor>b__3); } int countOf = Enumerable.Where<string>(aListOfStrings, CS$<>9__CachedAnonymousMethodDelegate4).Count<string>(); } }
-
Hi.
Could you send me a self-contained example of the failure to decompile? As far as I know, that support for .net 4 should not have changed anything in this area.
If I take the code you gave and compile it, I seepublic ReflectorExample() { List<string> list = new List<string> { "One", "Two", "Three" }; (from item in list where item.Length == 3 select item).Count<string>(); }
unless I have the optimisation level (View/Options/Optimization) set to less than 3.5. -
Code code above is compiled in VS2008 using .NET 3.5
I see no difference using any optimization settings from 2.0 through to 4.0
My reflector version is 6.5.0.135.
What you posted is what I used to see when I selected .NET 3.5 optimization, but I prefer the method syntax so I set my optimization to 2.0.
Somewhere in the upgrade path from 5.x it changed. -
I can now reproduce what you're seeing.
It happens if the 3.5 application is decompiled in a situation where the 4.0 version of System.Core is included in the assembly set. I imagine you have an assembly list set up for .NET 4 and have opened the 3.5 assembly in that set.
I didn't see it because I had System.Core 3.5 selected in my loaded assemblies since I was using a 3.5 framework set of assemblies in my assembly list.
I'll look into it. The workaround is to set up a .NET 3.5 assembly list, using say, File/Open List, Add, Framework35, double-click framework 35, select the 3.5 framework. Opening the assembly within this group of pre-loaded assemblies should give you the behaviour you are looking for. -
Thanks Clive...
I reset my list to Framework 3.5 and I now see the correct syntax.
Now if only I could see the code using Method syntax instead of Linq, like the original code, everything would be perfect 8) -
Using View/Options to turn the optimization down to .NET2 gives something pretty close to the original.
int num = source.Where<string>(delegate (string item) { return (item.Length == 3); }).Count<string>();
-
Hi
It looks like I have (almost) the same problem, but I can't solve it. Reflector version: 6.5.0.135.The workaround is to set up a .NET 3.5 assembly list, using say, File/Open List, Add, Framework35, double-click framework 35, select the 3.5 framework. Opening the assembly within this group of pre-loaded assemblies should give you the behaviour you are looking for.
Done.
Original code:using System; using System.Collections; namespace Crh.GbSheets { public class GbsElems : IEnumerable { private ArrayList items; public GbsElems() { items = new ArrayList(); } public IEnumerator GetEnumerator() { return items.GetEnumerator(); } public IEnumerable Reverse { get { for (int i = items.Count - 1; i >= 0; i--) yield return items[i]; } } } }
Reflectored code:public IEnumerable Reverse { get { return new <get_Reverse>d__0(-2) { <>4__this = this }; } } // Nested Types [CompilerGenerated] private sealed class <get_Reverse>d__0 : IEnumerable<object>, IEnumerable, IEnumerator<object>, IEnumerator, IDisposable { ...
Optimization in option is set to .NET 3.5, but using 2.0 is (almost) the same.
My main problem is the reflectored code does not compile. Is it possible to get something compileable?
Thank you very much,
Gyula -
Naming convention of temp variables does not make sense to the compiler also:
internal static double ConvertToDouble( object o ) { if (o is DateTime) { return (double)(((DateTime)o).Ticks); } else if (o is IConvertible) { return System.Convert.ToDouble(o); } throw new System.Exception( "Invalid datatype" ); }
becomes:internal static double ConvertToDouble(object o) { if (o is DateTime) { DateTime CS$0$0002 = (DateTime) o; return (double) CS$0$0002.Ticks; } if (!(o is IConvertible)) { throw new Exception("Invalid datatype"); } return Convert.ToDouble(o); }
Any idea on this one? -
Hi.
In the first example, the code is defining an Enumerable using the yield form. The C# compiler code generates this by defining an anonymous class which implements a state machine that generates the items. Currently, Reflector does not decompile this state machine back into code that uses the yield statement.
In the second example, the CS$0$0002 is a temporary variable that the C# compiler has generated. These symbols are present in a pdb file associated with the assembly. Reflector will use the names from the pdb file if it can find it, but only if the option View/Options/Disassembler/Show PDB symbols is checked. Unchecking the option will get rid of the variable. -
Thank you very much for the support!Clive Tong wrote:Currently, Reflector does not decompile this state machine back into code that uses the yield statement.
Is it possible to get a code from Reflector which compiles? -
No. You'll have to hand edit it to get it to compile.
Add comment
Please sign in to leave a comment.
this.ExpandStoryboard = (VisualStateManager.GetVisualStateGroups(child) as Collection<VisualStateGroup>).Where<VisualStateGroup>(delegate (VisualStateGroup stategroup) {
return (stategroup.Name == "PopupStates");
}).SelectMany(delegate (VisualStateGroup stategroup) {
return (stategroup.States as Collection<VisualState>);
}, delegate (VisualStateGroup stategroup, VisualState state) {
return new { stategroup = stategroup, state = state };
}).Where(delegate (<>f__AnonymousType0<VisualStateGroup, VisualState> <>h__TransparentIdentifier3) {
return (<>h__TransparentIdentifier3.state.Name == "PopupOpened");
}).Select(delegate (<>f__AnonymousType0<VisualStateGroup, VisualState> <>h__TransparentIdentifier3) {
return <>h__TransparentIdentifier3.state.Storyboard;
}).FirstOrDefault<Storyboard>();
but got error with following parts:
delegate (<>f__AnonymousType0<VisualStateGroup, VisualState> <>h__TransparentIdentifier3) {
return (<>h__TransparentIdentifier3.state.Name == "PopupOpened");
}).Select(delegate (<>f__AnonymousType0<VisualStateGroup, VisualState> <>h__TransparentIdentifier3) {
return <>h__TransparentIdentifier3.state.Storyboard;
what is the right code for above disassemble code?