我在 dnspy 中反编译了一些 Unity Dll 文件,得到了这行代码:
RuntimeHelpers.InitializeArray(array, fieldof(<PrivateImplementationDetails>.51A7A390CD6DE245186881400B18C9D822EFE240).FieldHandle);
我需要了解这行代码中的 fieldof() 函数,因为我是一个初学者,之前没见过它。
另外,我想知道为什么该行代码会报错。
在 MSIL 中,将 C# 代码(以及其他许多语言)编译成的中间语言中,有一个方便的 fieldof
运算符,它可以获取字段的 FieldInfo
。但是,在 C# 中,fieldof
并不存在。
在 C# 中,您需要执行以下操作:
var type = typeof(EnclosingClass); // "EnclosingClass" is the class this code is in
// assuming PrivateImplementationDetails is private
var fieldInfo = type.GetField("PrivateImplementationDetails", BindingFlags.NonPublic);
RuntimeHelpers.InitializeArray(array, fieldInfo.FieldHandle);
GetPreferredRenderTextureFormat
的 _class_
。RenderTextureFormat
是该方法的返回类型(它也可能是封闭类,但仅凭这段代码我无法确定)。 - Sweeper我建议从C# 8.0开始阅读以下内容,以了解每个版本的新功能。
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
在早期,我们习惯于实现以下类似的属性:private string userName;
public string UserName
{
get { return userName; }
set { userName = value; }
}
所以,当您反编译一个带有此属性的程序集时,您会看到反编译器输出完全像这样。
自从 C# 2.0 开始,并且一直在改进中,现在有多种实现 C# 属性的方式。
public string StringProperty1 => "String Property Value";
public string StringProperty2 { get; private set; }
public ICollection<double> Grades { get; } = new List<double>();
这里有什么共同点?
它们没有可读或可写的字段。这种声明类型的字段是由编译器创建并存储在名为PrivateImplementationDetails
的结构中的。这不一定是自己的字段。这只是运行时访问属性的自动生成的私有后备字段的方式。
例如,对于一个名为AProperty的int[]属性,将生成以下IL:
.field private int32[] '<AProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
当您查看设置此属性的类的构造函数IL时,可以看到它是像这样访问(支持)字段的:
IL_0009: ldc.i4.3
IL_000a: newarr [mscorlib]System.Int32
IL_000f: dup
IL_0010: ldtoken field valuetype '<PrivateImplementationDetails>{3CA49917-EFBC-4E01-A884-1CFF6283A97C}'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>{3CA49917-EFBC-4E01-A884-1CFF6283A97C}'::'$$method0x6000029-1'
IL_0015: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array,
FieldInfo
”。要保持原意,但使内容更易于理解。 - Sweeper