2013-07-09 5 views
2

Почему в C# вы не можете добавлять объекты в массив, если вы не объявляете длину массива или не добавляете элемент сразу? Например, я не мог просто сделать этоПочему вы не можете добавлять элементы в массивы в цикле?

foreach(object item in array) 
{ 
    array.Add(item) 
} 

Я бы создать список и преобразовать его в массив после цикла.

Я не хочу знать, как это сделать, я хочу, чтобы иметь логическую explination почему массивы фиксированной длины, но и другие коллекции нет (список, ListArray)

+6

Поскольку вы не можете изменить коллекцию, которую вы перечисляете в цикле foreach –

+3

'Array' не содержит метода' Add', поэтому вы должны использовать объект типа «Список» уже ... –

+1

Разве это не просто дублирование вашего элементы массива? – Sayse

ответ

5

Массивы не изменяемыми потому , что как работает память. Получение того, как распределение памяти работает именно в .NET, немного для SO-ответа, вы можете прочитать все об этом в другом месте, если хотите, но один аспект в основном универсален для каждой платформы: когда у вас есть часть памяти, выделенная для чего-то , следующий адрес после того, что что-то может быть частью какой-то другой вещи.

Таким образом, вы не можете просто расширить кусочек памяти и надеяться, что ничего не получится, вам нужно будет проверить, что вы можете расширить его и иметь план B, если вы не можете, - этот план B будет выделять новый блок памяти, копирование старой вещи в нее и освобождение старого блока.

Чтобы избежать перераспределения и копирование много раз, это обычная практика, чтобы сделать новый блок в два раза больше старый блок, так что если вы добавляете n детали, вы только перераспределить & Копируйте O(log n) раз, сохраняя amortized time for adding a new item to a dynamically-grown array down to O(1). Так что постоянное время, здорово - не совсем. Это еще больше времени, чем если бы вам не приходилось перераспределять, и на самом деле даже каждый add, что не, приводит к тому, что у роста есть немного накладных расходов, чтобы убедиться, что рост еще не требуется.

Итак, массивы, которые не растут, намного проще, немного быстрее и теряют память. Таким образом, в C# (и многих других языках, таких как Java и C++) вы можете выбрать: хотите ли вы использовать растущую «массивную вещь» или нерушимую? Там есть компромисс, и эти языки предпочитают не принимать это решение за вас.

+0

Мне очень нравится этот ответ, хотя он не слишком полезен для тех, кто, как мне кажется, все еще должен понять некоторые основы программирования. Небольшой намек для тех, кто мотивирован этим, сделать некоторые исследования: посмотрите на идею [Массив] (http://msdn.microsoft.com/de-de/library/9b9dty7d%28v=vs.80%29. aspx) s и в реализациях [List] (http://msdn.microsoft.com/de-de/library/vstudio/6sh2ey19.aspx) и [ArrayList] (http://msdn.microsoft.com/de -де/библиотека/System.Collections.ArrayList% 28v = vs.80% 29.aspx). Вы обнаружите, что все это имеет смысл. –

+0

Я знаю, как работают массивы. Это был просто плохо сформулированный вопрос, который люди неправильно поняли. –

+0

@HelloWorld это случается, я почти никогда не говорю о своих вопросах, так что другие люди понимают, что я пытаюсь спросить .. задавать вопрос сложнее, чем отвечать на вопрос :) – harold

10

Ответ на оригинал (до ответ был отредактирован):

Поскольку цикл foreach не динамически меняет свое конечное состояние, в то время как вы динамически изменяете объект, который он итерирует.

В вашем случае (если это было возможно) это никогда не закончится, поскольку в каждом цикле в массив добавляется один элемент.

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

int orgSize = array.Count 
for (var i = 0; i < orgSize; i++) 
{ 
    array.Add(array[i]) 
} 

Ответ на обновленный вопрос: почему массивы фиксированной длины, но и другие коллекции не являются (Список, ListArray):

Массивы фиксированной длины, вероятно, из-за исторических причин и сохранения обратной совместимости с C/C++. В этом «нормальном» массиве нет «Добавить», «Граф», они также не являются динамическими. Поэтому гораздо проще использовать List/ListArray и т. Д., Хотя это связано со стоимостью, например, с некоторой производительностью, и во всех случаях требуется больше памяти, потому что требуется администрирование для создания экземпляра. Однако, если это не проблема, я предпочитаю использовать типы List/ListArray/Dictionary из-за улучшения удобства использования.

+0

Добавление элемента в тот же массив, где вы зацикливаетесь? Не уверен, каким будет конечный результат. – Steve

+1

Возможно бесконечный цикл, поскольку вы используете длину массива как условие цикла ... –

+0

@ Все выше: я исправил проблему. –

3

Вы также можете просто пройти старомодный маршрут и использовать петлю. Это не знает о проблемах с изменением итератора и коллекции, и вам не нужен этот временный список (кажется довольно неэффективным).

1

На самом деле, ваш вопрос не ясен или не имеет смысла. Если вы пытаетесь заполнить существующий массив (с определенным размером, но нет значения), вы могли бы сделать что-то вроде этого:

var myArray = new string[5]; 

for(var i = 0; i < myArray.Length; i++) 
{ 
    myArray[i] = "Some value here..."; 
} 

Добавление существующих элементов в массив сам по себе не имеет смысла, однако.

Примечание: Метод Add() существует для List и т.д., но там, typicallye означает «Append этот элемент к концу моей коллекции».

Массив имеет определенную длину, которая не может быть изменена, поэтому вы не можете добавить к ней - только изменить существующие элементы.

4

Поскольку

  1. Массивы фиксированной длины с момента их объявления, вы не можете ни добавлять или удалять элементы. Вы можете создать новый массив с большей длиной и скопировать из одного в другой, но вы не можете динамически изменять длину массива.Вам может понадобиться List<> или какой-либо другой тип коллекции.

  2. Вы не можете изменить какую-либо коллекцию во время ее итерации (List, Dictionay, ArrayList и т. Д.), Это ограничение, которое создают разработчики языка/библиотеки. Разрешение этого будет связано с огромным объемом работы и будет иметь последствия для производительности, которые затрудняли бы производительность каждые цикла foreach, а не только те, в которых вы меняете коллекцию во время итерации.

Так Т.Л., д-р вы не могу, потому что это так, как он предназначен

Надеется, что это помогает.

+0

Это - то, что я искал. –

+0

@HelloWorld * * вы ищете? Обоснование того, почему массивы фиксированной длины? – harold

+0

Да, в сущности. –

2

Массивы имеют фиксированную длину. тем не менее, вы можете использовать цикл, чтобы заполнить их, если вы знаете нужный размер заранее:

var sourceArray = new string[100]; 
/* populate source */ 

var myArray = new string[sourceArray.Length]; 

for (var i = 0; i < sourceArray.Length; i++) 
{ 
    myArray[i] = sourceArray[i]; 
} 
Смежные вопросы