C#中的“fieldof()”方法是什么?

5

我在 dnspy 中反编译了一些 Unity Dll 文件,得到了这行代码:

RuntimeHelpers.InitializeArray(array, fieldof(<PrivateImplementationDetails>.51A7A390CD6DE245186881400B18C9D822EFE240).FieldHandle);

我需要了解这行代码中的 fieldof() 函数,因为我是一个初学者,之前没见过它。

另外,我想知道为什么该行代码会报错。


7
C# 中没有这样的语法。这是反编译器生成的。它可能意味着“获取此字段的FieldInfo”。要保持原意,但使内容更易于理解。 - Sweeper
1
请参见 https://github.com/jbevain/cecil/issues/141。 - Sweeper
@Sweeper,你能告诉我上传的那行代码没有错误的C#代码是什么吗? - user13214375
1
这有帮助吗?C# 中优雅的 infoof 运算符信息 - Abra
@Abra 是的,非常感谢!如果您愿意,您可以将其发布为此问题的答案。 - user13214375
2个回答

8

在 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);

感谢您的回答,我需要一点帮助。 - user13214375
private static RenderTextureFormat GetPreferredRenderTextureFormat() { RenderTextureFormat[] array = new RenderTextureFormat[3]; var type = typeof(RenderTextureFormat); var fieldInfo = type.GetField("PrivateImplementationDetail", BindingFlags.NonPublic); RuntimeHelpers.InitializeArray(array, fieldInfo.FieldHandle); foreach (RenderTextureFormat renderTextureFormat in array) { if (SystemInfo.SupportsRenderTextureFormat(renderTextureFormat)) return renderTextureFormat; } return RenderTextureFormat.Default; } - user13214375
在这段代码中,我是否正确地将对象传递给了 typeof 函数? - user13214375
不,往文件更上方看。找到包含 GetPreferredRenderTextureFormat_class_RenderTextureFormat 是该方法的返回类型(它也可能是封闭类,但仅凭这段代码我无法确定)。 - Sweeper
哦,好的,明白了。谢谢您在答案中提供的代码,它再次对我有很大帮助。 - user13214375

1

我建议从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,

而最后,在反编译输出中所看到的,仅仅意味着它在设置私有自动生成字段。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接