2016-09-29 2 views
2

Извините, если эта проблема уже возникла: я просмотрел заданные вопросы и искал Google, но не видел никаких объяснений.C#: массив основных типов по сравнению с массивом классов

Я начал использовать C#, после почти 30 лет C, несколько месяцев Java и пару лет C++ 15 лет назад ... что может объяснить мое недоумение. В C#, если я хочу массив междунар, я могу сделать:

int[] a = new int[10];

На данный момент, я могу получить доступ к элементам массива

a[0] = 1; // This is OK

теперь у меня есть класс (скажем, SomeClass), и я хочу, чтобы создать массив из них:

SomeClass[] o = new SomeClass[10] 

Я бы ожидать (для симметрии), что Я могу получить доступ к элементам массива, но

a[0].someField = val; // exception, must do a[0] = new SomeClass(); first 

Итак, первый new[] выделяет действительно только 10 указателей, а не 10 объектов, несмотря на синтаксис. Я должен повторить, что мои знания о C# не идеальны (:)), поэтому, пожалуйста, исправьте меня, если я ошибаюсь, но другая проблема с этим (помимо того, что, на мой взгляд, является путаницей между значениями и ссылками), является фрагментация памяти: с CI было бы выделено 10 «указателей» (malloc(10 * sizeof (void *));, затем выделено всю область (malloc(10 * sizeof (SomeClass))), затем использовались смещения для инициализации массива указателей, чтобы указать на область только malloc'd, сводя к минимуму фрагментацию памяти ... есть ли что-либо подобное ?. в C#

+0

Вместо указателей, подумайте о ссылках на C++. Классы C# называются ссылочными типами по определенной причине. Вы можете иметь массив экземпляров класса так же, как вы можете иметь экземпляр 'std :: vector'. Вы должны добавить что-то там, прежде чем сможете получить к нему доступ. –

+0

Если вы изменили его на «SomeStruct», но вы не можете получить массив «объектов», если они имеют ссылочный тип. – harold

ответ

2

в отличие от C++ массива типа класса, который имеет экземпляры классов, C# массив типа класса создает массив ссылок Это похоже на создание C++ массива указателей:

SomeClass *o[10] = {0}; 

Прежде чем сделать какой-либо доступ к o[i] вам нужно присвоить ему новый объект:

cout << o[0]->a;  // ERROR: o[0] is nullptr 
o[0] = new SomeClass; // Assign a new object 
cout << o[0]->a;  // Works fine 

Это так же, как это работает в C#: вы должны назначить объект к элементу массива перед доступом к его атрибутам.

Причина, по которой вам не нужно делать то же самое с int в C#, является то, что int является типом значения. Объявление массива типов значений заполняет элементы со значениями по умолчанию. Это относится также к пользовательским struct с.

+0

Спасибо, вот что я подумал. Я должен привыкнуть к новому синтаксису. В C это, на мой взгляд, более явное, ссылаетесь ли вы на «ссылки» (указатели, адреса) и объекты (области, на которые указывают адреса). –

+0

@MarcoBertoncin Вы можете думать о объектах с типизированным типом на C# с неявной звездочкой. Это упростило синтаксис за счет создания крошечной части первоначальной путаницы. – dasblinkenlight

+0

@MarcoBertoncin, также, посмотрите на типы значений vs Reference Types ([this] (http://stackoverflow.com/a/5057284/3276027) - хорошее начало).У них есть другое поведение с этой точки зрения: упрощение, переменная типа значения никогда не будет равна нулю. Int (фактически псевдоним для System.Int32 struct) является первым exaample значения типа –

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