嗯,我知道在C#中数组是一个对象 但一些代码混淆了我居然数组的结构是什么?
int[] numbers = {4, 5, 6, 1, 2, 3, -2, -1, 0};
foreach (int i in numbers)
Console.WriteLine(i);
在这个循环中它是一种访问访问任意对象int value= object.property;
的任意属性属性,但如何? 和这里的财产本身是什么?他们如何组织?
嗯,我知道在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>
其中T
代表一个特定的类型;你的情况int
(System.Int32
)
内存分配...
的int是32位长,并且想要的10个项目
int[] numbers = new int[10];
32×10的阵列= 320位内存分配
内存访问...
说你的阵列开始于0000:0000
,你要访问的数组的索引n [0-9]
...
伪代码...
index = n
addressof(n) = 0000:0000 + (sizeof(int) * index)
或
index = 2
addressof(n) = 0000:0000 + (32 * 2)
这是一个当您访问数组中的每个索引项时会发生什么的简化示例(您的foreach循环是这样做的)
foreach循环通过引用数组中的每个元素来工作(在你的情况下,引用被称为i)。
为什么你不在财产访问...
在阵列中,项目是由指数存储,而不是由名称...
...所以你不能.. 。
numbers.1
numbers.2
...但你可以...
numbers[1]
numbers[2]
由于每个Ø bject派生自对象,您可以访问特定类型的任意成员...
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());
}
我真的很好奇OP的问题是什么。当你说他们“会是对的”时,你是什么意思? –
OP只是想知道如何在不直接访问属性的情况下获得数组的实际值。他只是不明白IEnumerable和c#的“in”功能。 – DiscipleMichael
如何数据被存储
基本上阵列是数据的斑点。整数是32位有符号整数的值类型。
C#中的标识符是指向对象的指针或实际值。在引用类型的情况下,它们是真实的指针,在值类型的情况下(例如int,float等),它们是实际的数据。 int
是一个值类型,int[]
(数组到整数)是一个引用类型。
这样工作的原因基本上是“效率”:复制一个值类型的4字节或8字节的开销非常小,而复制整个数组的开销可能非常大。
如果您有一个包含N个整数的数组,它只不过是一个N * 4个字节的数组,其变量指向第一个元素。 blob中没有每个元素的名称。
例如为:
int[] foo = new int[10]; // allocates 40 bytes, naming the whole thing 'foo'
int f = foo[2]; // allocates variable 'f', copies the value of 'foo[2]' into 'f'.
访问数据
至于的foreach ...在C#中,所有集合实施一个名为IEnumerable<T>
的接口。如果你使用它,编译器会在这种情况下注意到它是一个整型数组,它将遍历所有元素。换句话说:
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
}
注意,我明确提出“在阵列的情况下”在这里。数组是C#编译器的特例。如果你不使用数组(但是f.ex.与List
,Dictionary
或更复杂的东西),它的工作原理有点不同,即使用Enumerator
和IDisposable
。请注意,这只是一个编译器优化,数组完全有能力处理IEnumerable
。如果你想有一个名字
你可能需要一个Dictionary
var e = myEnumerable.GetEnumerator();
try
{
while (e.MoveNext())
{
var f = e.Current;
// code
}
}
finally
{
IDisposable d = e as IDisposable;
if (d != null)
{
d.Dispose();
}
}
:
对于那些有兴趣,基本上它会产生这种非阵列和非字符串。
是的,正如你所说的,普通数组X []由编译器专门为'foreach'处理。 (我们知道这是因为在.Net 1.x中存在“foreach”,但在.Net 1.x中不存在“IEnumerable
@MatthewWatson嗯,是,不是。是的:在旧风格中,foreach曾经为某些案例施放过。 'foreach(myOldCollection中的字符串s)'这些值被转换为字符串。但是,它也与IL操作码有关,以及编译器可以使用ldlen操作码对字符串和数组进行简单优化 - 在这种情况下,它也不需要检查IDisposable '。 – atlaste
数组如何实现'IEnumerable'和朋友实际上是非常有趣的 - 有很多的运行时黑客入侵它。但就你的代码而言,即使数组类型本身既不是通用的,也不是“真正”实现该接口的'T []'实现'IEnumerable
你的问题有点不清楚;你可以试着重述它吗?问题的标题和您提供的两个代码片段之间似乎没有太多联系。例如,“int value = object.property”与问题或较大的代码片段有什么关系?你对C#中的数组的内部和实现细节有疑问吗?或者你对'foreach'循环语言结构感兴趣吗? –
你有JavaScript背景吗? – usr
这不会访问任何属性,只是遍历一个'IEnumerable'(一个数组实现的接口)并使用foreach循环访问此过程中的每个元素[MSDN] [https://msdn.microsoft.com/deta -at/library/ttw7t8t6.aspx] –
derpirscher