C# Can';我在.net reflector/其他反编译器中看到构造函数的代码
在.net反编译程序中,我无法看到构造函数的代码。我已经在许多.net反编译器中进行了测试,但没有一个显示构造函数代码。是否有任何反编译程序显示该代码 提前谢谢C# Can';我在.net reflector/其他反编译器中看到构造函数的代码,c#,.net,decompiling,decompiler,C#,.net,Decompiling,Decompiler,在.net反编译程序中,我无法看到构造函数的代码。我已经在许多.net反编译器中进行了测试,但没有一个显示构造函数代码。是否有任何反编译程序显示该代码 提前谢谢 显示构造函数代码。显示构造函数代码。所有由C#定义的.NET类型(我不知道VB.NET或其他语言是如何做到这一点的,它们可能会做同样的事情,也可能不会)都将有一个构造函数 如果没有显式添加构造函数,编译器将为您提供一个构造函数 我(早些时候)测试过JetBrains的Telerik反编译器、Reflector和dotPeek,当有代码要
显示构造函数代码。显示构造函数代码。所有由C#定义的.NET类型(我不知道VB.NET或其他语言是如何做到这一点的,它们可能会做同样的事情,也可能不会)都将有一个构造函数 如果没有显式添加构造函数,编译器将为您提供一个构造函数 我(早些时候)测试过JetBrains的Telerik反编译器、Reflector和dotPeek,当有代码要显示时,它们都会显示构造函数代码 下面是dotPeek 1.1,它显示了
元组的构造函数
:
由dotPeek反编译的构造函数1.1“>
但是,反编译器可能会选择删除构造函数,因为它看不到您的原始源代码,因此它会尝试推断什么样的代码将生成您提供给它的IL。因此,即使您的代码显式写出一个空构造函数,它的编译结果也可能与编译器为y提供的完全相同因此,反编译器假定您没有写出空构造函数
TL;DR:根据判断,它没有参数。因此,它的唯一目的可能是调用基本构造函数,而不是其他任何东西。因此,可能完全没有必要进行反编译,因为可能的情况是,源代码中也没有写出一个构造函数
然而,为了说明所有类都有构造函数,让我们看一些例子
通过执行代码,然后单击结果上方的IL按钮,可以在中测试以下示例,以查看反编译的IL。LINQPad的反编译器(mono.cecil I belive)不会对同一级别进行此类推断,因此它将显示构造函数
示例1:没有将放置在构造函数中的构造函数或代码
void Main()
{
var t = new Test();
t.Execute();
}
public class Test
{
public void Execute()
{
Debug.WriteLine("Execute");
}
}
生成的IL:
IL_0000: newobj UserQuery+Test..ctor
IL_0005: stloc.0 // t
IL_0006: ldloc.0 // t
IL_0007: callvirt UserQuery+Test.Execute
Test.Execute:
IL_0000: ldstr "Execute"
IL_0005: call System.Diagnostics.Debug.WriteLine
IL_000A: ret
Test..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
IL_0000: newobj UserQuery+Test..ctor
IL_0005: stloc.0 // t
IL_0006: ldloc.0 // t
IL_0007: callvirt UserQuery+Test.Execute
Test.Execute:
IL_0000: ldstr "Execute"
IL_0005: call System.Diagnostics.Debug.WriteLine
IL_000A: ret
Test..ctor:
IL_0000: ldarg.0
IL_0001: ldsfld System.String.Empty
IL_0006: stfld UserQuery+Test._Value
IL_000B: ldarg.0
IL_000C: call System.Object..ctor
IL_0011: ret
如您所见,其中有一个构造函数,但它所做的只是从System.Object
调用基本构造函数
示例2:添加带有默认值的字符串字段
void Main()
{
var t = new Test();
t.Execute();
}
public class Test
{
public void Execute()
{
Debug.WriteLine("Execute");
}
}
现在让我们做些其他事情,将此字段添加到类:
public class Test
{
private string _Value = string.Empty;
public void Execute()
{
Debug.WriteLine("Execute");
}
}
重新运行,以下是生成的IL:
IL_0000: newobj UserQuery+Test..ctor
IL_0005: stloc.0 // t
IL_0006: ldloc.0 // t
IL_0007: callvirt UserQuery+Test.Execute
Test.Execute:
IL_0000: ldstr "Execute"
IL_0005: call System.Diagnostics.Debug.WriteLine
IL_000A: ret
Test..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
IL_0000: newobj UserQuery+Test..ctor
IL_0005: stloc.0 // t
IL_0006: ldloc.0 // t
IL_0007: callvirt UserQuery+Test.Execute
Test.Execute:
IL_0000: ldstr "Execute"
IL_0005: call System.Diagnostics.Debug.WriteLine
IL_000A: ret
Test..ctor:
IL_0000: ldarg.0
IL_0001: ldsfld System.String.Empty
IL_0006: stfld UserQuery+Test._Value
IL_000B: ldarg.0
IL_000C: call System.Object..ctor
IL_0011: ret
如您所见,初始化代码被“提升”到构造函数中,因此构造函数现在初始化字段
示例3:将初始化移动到构造函数中
void Main()
{
var t = new Test();
t.Execute();
}
public class Test
{
public void Execute()
{
Debug.WriteLine("Execute");
}
}
让我们将类更改为:
public class Test
{
private string _Value;
public Test()
{
_Value = string.Empty;
}
public void Execute()
{
Debug.WriteLine("Execute");
}
}
下面是构造函数的IL:
Test..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ldarg.0
IL_0007: ldsfld System.String.Empty
IL_000C: stfld UserQuery+Test._Value
IL_0011: ret
这里的区别在于构造函数中代码的顺序,该字段在调用基本构造函数之后初始化,而在前面的示例中,它是在调用基本构造函数之前初始化的
结论
void Main()
{
var t = new Test();
t.Execute();
}
public class Test
{
public void Execute()
{
Debug.WriteLine("Execute");
}
}
这些类型中可能没有构造函数,或者这些反编译器不知道在声明中初始化字段与在构造函数中初始化字段之间的区别。但是,我发现后者不太可能,因此我假设该类没有构造函数。所有由C#定义的.NET类型(我不知道VB.NET或其他语言是如何做到这一点的,他们可能会做同样的事情,他们可能不会)将有一个构造函数 如果没有显式添加构造函数,编译器将为您提供一个构造函数 我(早些时候)测试过JetBrains的Telerik反编译器、Reflector和dotPeek,当有代码要显示时,它们都会显示构造函数代码 下面是dotPeek 1.1,它显示了
元组的构造函数
:
由dotPeek反编译的构造函数1.1“>
但是,反编译器可能会选择删除构造函数,因为它看不到您的原始源代码,因此它会尝试推断什么样的代码将生成您提供给它的IL。因此,即使您的代码显式写出一个空构造函数,它的编译结果也可能与编译器为y提供的完全相同因此,反编译器假定您没有写出空构造函数
TL;DR:根据判断,它没有参数。因此,它的唯一目的可能是调用基本构造函数,而不是其他任何东西。因此,可能完全没有必要进行反编译,因为可能的情况是,源代码中也没有写出一个构造函数
然而,为了说明所有类都有构造函数,让我们看一些例子
通过执行代码,然后单击结果上方的IL按钮,可以在中测试以下示例,以查看反编译的IL。LINQPad的反编译器(mono.cecil I belive)不会对同一级别进行此类推断,因此它将显示构造函数
示例1:没有将放置在构造函数中的构造函数或代码
void Main()
{
var t = new Test();
t.Execute();
}
public class Test
{
public void Execute()
{
Debug.WriteLine("Execute");
}
}
生成的IL:
IL_0000: newobj UserQuery+Test..ctor
IL_0005: stloc.0 // t
IL_0006: ldloc.0 // t
IL_0007: callvirt UserQuery+Test.Execute
Test.Execute:
IL_0000: ldstr "Execute"
IL_0005: call System.Diagnostics.Debug.WriteLine
IL_000A: ret
Test..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
IL_0000: newobj UserQuery+Test..ctor
IL_0005: stloc.0 // t
IL_0006: ldloc.0 // t
IL_0007: callvirt UserQuery+Test.Execute
Test.Execute:
IL_0000: ldstr "Execute"
IL_0005: call System.Diagnostics.Debug.WriteLine
IL_000A: ret
Test..ctor:
IL_0000: ldarg.0
IL_0001: ldsfld System.String.Empty
IL_0006: stfld UserQuery+Test._Value
IL_000B: ldarg.0
IL_000C: call System.Object..ctor
IL_0011: ret
如您所见,其中有一个构造函数,但它所做的只是从System.Object
调用基本构造函数
示例2:添加带有默认值的字符串字段
void Main()
{
var t = new Test();
t.Execute();
}
public class Test
{
public void Execute()
{
Debug.WriteLine("Execute");
}
}
现在让我们做些其他事情,将此字段添加到类:
public class Test
{
private string _Value = string.Empty;
public void Execute()
{
Debug.WriteLine("Execute");
}
}
重新运行,以下是生成的IL:
IL_0000: newobj UserQuery+Test..ctor
IL_0005: stloc.0 // t
IL_0006: ldloc.0 // t
IL_0007: callvirt UserQuery+Test.Execute
Test.Execute:
IL_0000: ldstr "Execute"
IL_0005: call System.Diagnostics.Debug.WriteLine
IL_000A: ret
Test..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
IL_0000: newobj UserQuery+Test..ctor
IL_0005: stloc.0 // t
IL_0006: ldloc.0 // t
IL_0007: callvirt UserQuery+Test.Execute
Test.Execute:
IL_0000: ldstr "Execute"
IL_0005: call System.Diagnostics.Debug.WriteLine
IL_000A: ret
Test..ctor:
IL_0000: ldarg.0
IL_0001: ldsfld System.String.Empty
IL_0006: stfld UserQuery+Test._Value
IL_000B: ldarg.0
IL_000C: call System.Object..ctor
IL_0011: ret
如您所见,初始化代码被“提升”到构造函数中,因此构造函数现在初始化字段
示例3:将初始化移动到构造函数中
void Main()
{
var t = new Test();
t.Execute();
}
public class Test
{
public void Execute()
{
Debug.WriteLine("Execute");
}
}
让我们将类更改为:
public class Test
{
private string _Value;
public Test()
{
_Value = string.Empty;
}
public void Execute()
{
Debug.WriteLine("Execute");
}
}
下面是构造函数的IL:
Test..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ldarg.0
IL_0007: ldsfld System.String.Empty
IL_000C: stfld UserQuery+Test._Value
IL_0011: ret
这里的区别在于构造函数中代码的顺序,该字段在调用基本构造函数之后初始化,而在前面的示例中,它是在调用基本构造函数之前初始化的
结论
void Main()
{
var t = new Test();
t.Execute();
}
public class Test
{
public void Execute()
{
Debug.WriteLine("Execute");
}
}
这些类型中可能没有构造函数,或者这些反编译器不知道它们之间的区别