7

System.Array用作公共语言运行时 (CLR) 中所有数组的基类。根据这篇文章

对于每个具体的数组类型,[the] 运行时添加三个特殊方法:Get// SetAddress

事实上,如果我反汇编这段 C# 代码,

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

进入 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)

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

特别是,我想知道是否有可能获得一个MethodInfo对象以GetSet使用,Reflection.Emit而不必创建一个具有正确类型和维度的数组实例来反映,就像在链接示例中所做的那样。

4

3 回答 3

6

看这里,特别是第 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 的返回类型为 void。此方法用于设置数组的特定元素,其中参数指定每个维度的索引,从要设置的元素的第一个开始,最后一个参数指定要存储到目标元素中的值。

• 一个Address 方法,它采用一系列int32 参数,数组的每个维度一个,返回类型是指向数组元素类型的托管指针。此方法用于返回指向数组的特定元素的托管指针,其中参数指定要返回其地址的元素的每个维度的索引,从第一个维度开始。

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

于 2010-03-31T19:24:50.167 回答
3

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

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

将努力获取Get该类型的方法string[,,,,,]

于 2010-03-31T20:32:59.337 回答
1

我不确定它是否会解决您非常具体的问题,但关于该主题的一篇很棒的文字(除其他外)是CLR via C#。它对您感兴趣的许多主题非常深入,并花费大量时间与反汇编程序一起研究许多基本 .NET 类型(包括数组)的内部工作原理。绝对值得一试。

于 2010-03-31T19:24:34.790 回答