2016-03-21 2 views
1

Ну, я знаю, что массив в C# является объектом , но немного коды спутали меня на самом делеКакова структура массива?

int[] numbers = {4, 5, 6, 1, 2, 3, -2, -1, 0}; 
foreach (int i in numbers)  
     Console.WriteLine(i); 

для доступа произвольного свойства произвольного объекта int value= object.property;

в этом цикле это своего рода доступ свойства, но как? и какая здесь недвижимость? как они организованы?

+5

Ваш вопрос немного неясен; можете ли вы попытаться его повторить? Между заголовком вопроса и двумя фрагментами кода, которые вы предоставляете, похоже, не очень много. Например, как «int value = object.property» относится к вопросу или к большому фрагменту кода? Является ли ваш вопрос о внутренних деталях и деталях реализации массива в C#, или вам интересно узнать о конструкции языка цикла foreach? –

+2

У вас есть JavaScript-фона? – usr

+5

Это не имеет доступа к каким-либо свойствам, но просто выполняет итерацию над 'IEnumerable ' (интерфейс, который реализует массивы) и обращается к каждому элементу этого процесса с использованием цикла foreach [MSDN] [https://msdn.microsoft.com/de -at/library/ttw7t8t6.aspx] – derpirscher

ответ

0

Массив - это просто коллекция, или 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()); 
} 
+0

Мне действительно интересно, что вопрос OP. Когда вы говорите, что они «были бы правы», что вы имеете в виду? –

+0

OP просто интересовался, как вы можете получить фактические значения массива без прямого доступа к свойству. Он просто не понимал функции IEnumerable и «in» C#. – DiscipleMichael

3

Как данные хранятся

В основном массив является блоб данных. Целые значения представляют собой типы значений 32-разрядных целых чисел.

Идентификаторы в C# являются либо указателями на объекты, либо действительными значениями. В случае ссылочных типов они являются реальными указателями, в случае типов значений (например, int, float и т. Д.) Они являются фактическими данными. int - тип значения, int[] (массив целым числам) является ссылочным типом.

Причина, по которой это работает, в основном «эффективность»: накладные расходы на копирование 4 байта или 8 байтов для типа значения очень малы, а накладные расходы на копирование всего массива могут быть довольно обширными.

Если у вас есть массив, содержащий N целых чисел, это не более чем пятно N * 4 байта, с переменной, указывающей на первый элемент. Для каждого элемента в блоке нет имени.

т.д .:

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'. 

Доступ к данным

Что касается Еогеасп ... В 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.

Для тех, кто заинтересован, в основном это будет генерировать это для не-массивов и не являющихся строками:

var e = myEnumerable.GetEnumerator(); 
try 
{ 
    while (e.MoveNext()) 
    { 
     var f = e.Current; 
     // code 
    } 
} 
finally 
{ 
    IDisposable d = e as IDisposable; 
    if (d != null) 
    { 
     d.Dispose(); 
    } 
} 

Если вы хотите имя

Вы, вероятно, нужно Dictionary.

+0

Да, как вы говорите, простые массивы X [] обрабатываются специально компилятором для 'foreach'. (И мы знаем это, потому что 'foreach' существует в .Net 1.x, но' IEnumerable 'НЕ существует в .Net 1.x.) –

+0

@MatthewWatson Ну, да и нет. Да: в старом стиле foreach используется для броска в определенных случаях. 'foreach (строка s в myOldCollection)', где значения были приведены к строкам. Тем не менее, это также связано с кодами операций IL и тривиальной оптимизацией, которую компилятор может сделать (как для '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'ldlen ' '. – atlaste

+0

Как массивы реализуют 'IEnumerable' и друзей на самом деле довольно интересно - там много взлома runtime. Но что касается вашего кода, 'T []' реализует 'IEnumerable ', хотя сам тип массива не является ни общим, ни« действительно »реализует интерфейс. Дым и зеркала :) – Luaan

Смежные вопросы