C# 数组的结构是什么?
我知道C#中的数组是一个对象 但实际上有一点代码把我弄糊涂了C# 数组的结构是什么?,c#,arrays,foreach,C#,Arrays,Foreach,我知道C#中的数组是一个对象 但实际上有一点代码把我弄糊涂了 int[] numbers = {4, 5, 6, 1, 2, 3, -2, -1, 0}; foreach (int i in numbers) Console.WriteLine(i); 访问任意对象的任意属性int value=object.property 在这个循环中,它有点像访问属性,但是如何访问呢? 这里的地产是什么?它们是如何组织的?数组只是一个集合,或者IEnumerable其中T表示特
int[] numbers = {4, 5, 6, 1, 2, 3, -2, -1, 0};
foreach (int i in numbers)
Console.WriteLine(i);
访问任意对象的任意属性int value=object.property代码>
在这个循环中,它有点像访问属性,但是如何访问呢?
这里的地产是什么?它们是如何组织的?数组只是一个集合,或者IEnumerable
其中T
表示特定类型;在您的情况下,int
(System.Int32
)
内存分配…
int的长度为32位,您需要一个包含10项的数组
int[]数字=新的int[10]代码>
32 x 10=分配的320位内存
内存访问…
假设你的数组从0000:0000开始,你想访问数组的索引n[0-9]
伪代码
index = n
addressof(n) = 0000:0000 + (sizeof(int) * index)
或
这是一个简化的示例,说明了当您访问数组中的每个索引项时会发生什么(您的foreach循环就是这样做的)
foreach循环通过引用数组中的每个元素来工作(在您的例子中,该引用称为i)
为什么不按属性访问…
在数组中,项是按索引存储的,而不是按名称存储的
。。。所以你不能
numbers.1
numbers.2
…但是你可以
numbers[1]
numbers[2]
由于每个对象都是从对象派生的,所以您可以访问特定类型的任意成员
numbers[1].GetHashCode();
示例:
//Define an array if integers, shorthand (see, memory allocation)...
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//For each element in the array (under the hood, get the element's address in memory and hold this in a reference called i)...
foreach(int i in numbers)
{
// Call GetHashCode() on the instance pointed to by i and pass the reference (by value) to the Console.WriteLine method.
Console.WriteLine(i.GetHashCode());
}
数据的存储方式
基本上,数组是一个数据块。整数是32位有符号整数的值类型
C#中的标识符要么是指向对象的指针,要么是实际值。对于引用类型,它们是实指针;对于值类型(例如int、float等),它们是实际数据int
是一种值类型,int[]
(数组到整数)是一种引用类型
它这样工作的原因基本上是“效率”:为值类型复制4字节或8字节的开销非常小,而复制整个数组的开销可能非常大
如果你有一个包含N个整数的数组,它只不过是一个N*4字节的blob,变量指向第一个元素。blob中的每个元素都没有名称
例如:
访问数据
至于foreach。。。在C#中,所有集合都实现一个名为IEnumerable
的接口。如果您使用它,编译器将在本例中注意到它是一个整数数组,它将遍历所有元素。换言之:
foreach (int f in foo) // copy value foo[0] into f, then foo[1] into f, etc
{
// code
}
(对于数组!)与以下内容完全相同:
for (int i=0; i<foo.Length; ++i)
{
int f = foo[i];
// code
}
如果你想要一个名字
你可能需要一本字典
你的问题有点不清楚;你能再说一遍吗?问题的标题和您提供的两个代码片段之间似乎没有太多联系。例如,int value=object.property
与问题或更大的代码段有什么关系?您是否对C#中数组的内部结构和实现细节有疑问,或者您是否对foreach
循环语言构造感兴趣?您是否有JavaScript背景?这不会访问任何属性,只会迭代IEnumerable
(数组实现的接口)并使用foreach循环[MSDN]访问此过程中的每个元素[我认为您对属性是什么感到困惑。数组中的数字不是属性。例如,属性就是数组长度。foreach在数组中所做的是在引擎盖下创建for循环。如果它不是数组,而是列表或字典,它将创建哈希集并实现GetEnumerator(),并使用MoveNext()和Current()来枚举集合。@derpirscher实际上不是这样。foreach
用于数组(和字符串)编译为true for循环,不涉及IEnumerable
中的枚举数。在验证时,它可能会检查它的存在,但我甚至对此表示怀疑。在这里,您可以自己看看发生了什么:;查看IL——那里没有枚举数。不过,在较高的级别上,您对它的作用是正确的。是的,正如您所说,普通数组X[]是由编译器专门为foreach
处理的(我们知道这一点是因为foreach
存在于.Net 1.x中,但IEnumerable
不存在于.Net 1.x中)。@MatthewWatson好的,是和否。是:在旧样式中,foreach用于对某些情况进行强制转换。foreach(myOldCollection中的字符串s)
将值强制转换为字符串。但是,这也与IL操作码和编译器可以进行的琐碎优化有关(对于字符串和数组)使用ldlen
操作码-在这种情况下,它也不需要检查IDisposable
。数组的foreach
与IEnumerable
之间的一个很大区别是,为后者生成的IL代码将调用IEnumerator.GetEnumerator()
和IEnumerator.MoveNext()
,而前者不进行任何此类调用(因此速度更快)。数组与数组的IL反编译代码foreach示例:Print1()
和Print2()
生成完全相同的IL代码。作为旁注,非数组类型的foreach
欺骗并使用duck类型作为可枚举的主要源,而不是IEnumerable
/IEnumerable
。例如,我真的很好奇OP的问题是什么。当你说他们“是对的”时,你是什么意思?OP只是想知道如何在不直接访问属性的情况下获得数组的实际值。他只是不理解IEnumerable和c#的“in”功能。
foreach (int f in foo) // copy value foo[0] into f, then foo[1] into f, etc
{
// code
}
for (int i=0; i<foo.Length; ++i)
{
int f = foo[i];
// code
}
var e = myEnumerable.GetEnumerator();
try
{
while (e.MoveNext())
{
var f = e.Current;
// code
}
}
finally
{
IDisposable d = e as IDisposable;
if (d != null)
{
d.Dispose();
}
}