在哪里可以找到有关 .NET 中多维 System.Array 实例的 Get、Set 和 Address 方法的信息?

发布于 2024-08-26 22:40:45 字数 2792 浏览 4 评论 0原文

System.Array 作为所有数组的基类公共语言运行时 (CLR)。根据这篇文章< /a>:

对于每种具体数组类型,运行时添加了三个特殊方法:Get/Set/Address

事实上,如果我

int[,] x = new int[1024,1024];
x[0,0] = 1;
x[1,1] = 2;
x[2,2] = 3;
Console.WriteLine(x[0,0]);
Console.WriteLine(x[1,1]);
Console.WriteLine(x[2,2]);

将这段 C# 代码反汇编成 CIL,

IL_0000:  ldc.i4     0x400
IL_0005:  ldc.i4     0x400
IL_000a:  newobj     instance void int32[0...,0...]::.ctor(int32,
                                                         int32)
IL_000f:  stloc.0
IL_0010:  ldloc.0
IL_0011:  ldc.i4.0
IL_0012:  ldc.i4.0
IL_0013:  ldc.i4.1
IL_0014:  call       instance void int32[0...,0...]::Set(int32,
                                                       int32,
                                                       int32)
IL_0019:  ldloc.0
IL_001a:  ldc.i4.1
IL_001b:  ldc.i4.1
IL_001c:  ldc.i4.2
IL_001d:  call       instance void int32[0...,0...]::Set(int32,
                                                       int32,
                                                       int32)
IL_0022:  ldloc.0
IL_0023:  ldc.i4.2
IL_0024:  ldc.i4.2
IL_0025:  ldc.i4.3
IL_0026:  call       instance void int32[0...,0...]::Set(int32,
                                                       int32,
                                                       int32)
IL_002b:  ldloc.0
IL_002c:  ldc.i4.0
IL_002d:  ldc.i4.0
IL_002e:  call       instance int32 int32[0...,0...]::Get(int32,
                                                        int32)
IL_0033:  call       void [mscorlib]System.Console::WriteLine(int32)
IL_0038:  ldloc.0
IL_0039:  ldc.i4.1
IL_003a:  ldc.i4.1
IL_003b:  call       instance int32 int32[0...,0...]::Get(int32,
                                                        int32)
IL_0040:  call       void [mscorlib]System.Console::WriteLine(int32)
IL_0045:  ldloc.0
IL_0046:  ldc.i4.2
IL_0047:  ldc.i4.2
IL_0048:  call       instance int32 int32[0...,0...]::Get(int32,
                                                        int32)
IL_004d:  call       void [mscorlib]System.Console::WriteLine(int32)

可以清楚地看到对上述 GetSet 方法的调用。这些方法的数量似乎与数组的维数有关,这可能就是它们由运行时创建并且不预先声明的原因。我在 MSDN 上找不到有关这些方法的任何信息,而且它们简单的名称使它们无法通过 Google 搜索。我正在为支持多维数组的语言编写一个编译器,因此我想找到一些有关这些方法的官方文档,在什么条件下我可以期望它们存在以及我可以期望它们的签名是什么。

特别是,我想知道是否可以为 GetSet 获取 MethodInfo 对象以与 Reflection 一起使用。发射,而无需创建具有正确类型和维度的数组实例来反映,如链接示例中所做的那样。

System.Array serves as the base class for all arrays in the Common Language Runtime (CLR). According to this article:

For each concrete array type, [the] runtime adds three special methods: Get/Set/Address.

and indeed if I disassemble this C# code,

int[,] x = new int[1024,1024];
x[0,0] = 1;
x[1,1] = 2;
x[2,2] = 3;
Console.WriteLine(x[0,0]);
Console.WriteLine(x[1,1]);
Console.WriteLine(x[2,2]);

into CIL I get,

IL_0000:  ldc.i4     0x400
IL_0005:  ldc.i4     0x400
IL_000a:  newobj     instance void int32[0...,0...]::.ctor(int32,
                                                         int32)
IL_000f:  stloc.0
IL_0010:  ldloc.0
IL_0011:  ldc.i4.0
IL_0012:  ldc.i4.0
IL_0013:  ldc.i4.1
IL_0014:  call       instance void int32[0...,0...]::Set(int32,
                                                       int32,
                                                       int32)
IL_0019:  ldloc.0
IL_001a:  ldc.i4.1
IL_001b:  ldc.i4.1
IL_001c:  ldc.i4.2
IL_001d:  call       instance void int32[0...,0...]::Set(int32,
                                                       int32,
                                                       int32)
IL_0022:  ldloc.0
IL_0023:  ldc.i4.2
IL_0024:  ldc.i4.2
IL_0025:  ldc.i4.3
IL_0026:  call       instance void int32[0...,0...]::Set(int32,
                                                       int32,
                                                       int32)
IL_002b:  ldloc.0
IL_002c:  ldc.i4.0
IL_002d:  ldc.i4.0
IL_002e:  call       instance int32 int32[0...,0...]::Get(int32,
                                                        int32)
IL_0033:  call       void [mscorlib]System.Console::WriteLine(int32)
IL_0038:  ldloc.0
IL_0039:  ldc.i4.1
IL_003a:  ldc.i4.1
IL_003b:  call       instance int32 int32[0...,0...]::Get(int32,
                                                        int32)
IL_0040:  call       void [mscorlib]System.Console::WriteLine(int32)
IL_0045:  ldloc.0
IL_0046:  ldc.i4.2
IL_0047:  ldc.i4.2
IL_0048:  call       instance int32 int32[0...,0...]::Get(int32,
                                                        int32)
IL_004d:  call       void [mscorlib]System.Console::WriteLine(int32)

where the calls to the aforementioned Get and Set methods can be clearly seen. It seems the arity of these methods is related to the dimensionality of the array, which is presumably why they are created by the runtime and are not pre-declared. I couldn't locate any information about these methods on MSDN and their simple names makes them resistant to Googling. I'm writing a compiler for a language which supports multidimensional arrays, so I'd like to find some official documentation about these methods, under what conditions I can expect them to exist and what I can expect their signatures to be.

In particular, I'd like to know whether its possible to get a MethodInfo object for Get or Set for use with Reflection.Emit without having to create an instance of the array with correct type and dimensionality on which to reflect, as is done in the linked example.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

屌丝范 2024-09-02 22:40:45

看这里,特别是第 63-65 页的 14.2 节

http://download.microsoft.com/download/7/3/3/733AD403-90B2-4064-A81E-01035A7FE13C/MS%20Partition%20II.pdf

但要点,您可以从 IL 看出,它们是处理给定索引位置处的数组的 getter 和 setter 方法。

• 一个 Get 方法,它接受一系列
int32 参数,每个参数一个
数组的维度,并返回
类型为元素类型的值
数组的。该方法用于
访问数组的特定元素
其中参数指定索引
进入每个维度,从
元素的第一个
返回。

• 采用序列的 Set 方法
int32 参数,每个参数一个
数组的维度,后跟
类型为元素类型的值
数组的。 Set的返回类型
无效。该方法用于设置一个
数组的特定元素,其中
参数指定索引
每个维度,从
首先,要设置的元素和
最后一个参数指定值
存储到目标元素中。

• 一个 Address 方法,它采用
int32 参数序列,其中一个用于
数组的每个维度,并且有一个
返回类型是托管指针
数组的元素类型。这
方法用于返回托管的
指向特定元素的指针
数组,其中参数指定
索引到每个维度,开始
与第一个元素的
地址将被返回。

编辑:这是使用文档页码编号的第 63-65 页。实际 PDF 中的 73-75。

Look here, specifically section 14.2 on pages 63-65

http://download.microsoft.com/download/7/3/3/733AD403-90B2-4064-A81E-01035A7FE13C/MS%20Partition%20II.pdf

But the takeaway, and you can tell from the IL, is that they're the getter and setter methods for dealing with arrays at the given index positions.

• A Get method that takes a sequence of
int32 arguments, one for each
dimension of the array, and returns a
value whose type is the element type
of the array. This method is used to
access a specific element of the array
where the arguments specify the index
into each dimension, beginning with
the first, of the element to be
returned.

• A Set method that takes a sequence
of int32 arguments, one for each
dimension of the array, followed by a
value whose type is the element type
of the array. The return type of Set
is void. This method is used to set a
specific element of the array where
the arguments specify the index into
each dimension, beginning with the
first, of the element to be set and
the final argument specifies the value
to be stored into the target element.

• An Address method that takes a
sequence of int32 arguments, one for
each dimension of the array, and has a
return type that is a managed pointer
to the array’s element type. This
method is used to return a managed
pointer to a specific element of the
array where the arguments specify the
index into each dimension, beginning
with the first, of the element whose
address is to be returned.

Edit: That's pages 63-65 using the document's page numbering. 73-75 in the actual PDF.

烧了回忆取暖 2024-09-02 22:40:45

要回答第二个问题,您不需要创建实例来获取这些方法的 MethodInfo 。类似的方法

var mi = typeof(string).MakeArrayType(6).GetMethod("Get");

可以获取 string[,,,,,] 类型的 Get 方法。

To answer your second question, you don't need to create an instance to get a MethodInfo for these methods. Something like

var mi = typeof(string).MakeArrayType(6).GetMethod("Get");

will work to get the Get method for the string[,,,,,] type.

焚却相思 2024-09-02 22:40:45

我不确定它是否能解决您非常具体的问题,但关于该主题(除其他外)的精彩文本是 通过 C# 进行 CLR。它对您感兴趣的许多主题进行了非常深入的研究,并花费大量时间使用反汇编程序来查看许多基本 .NET 类型(包括数组)的内部工作原理。绝对值得一看。

I'm not sure if it will address your very specific question but a great text on the subject (among others) is CLR via C#. It gets very in-depth for many of the topics you're interested in and spends a lot of time with the disassembler looking at the inner workings of many base .NET types including arrays. Definitely worth checking out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文