Тип int [] ссылочный или тип значения?


124

Я знаю, что int - это тип значения, но что такое массивы типов значений? Справочные типы? Типы значений? Я хочу передать массив функции, чтобы что-то проверить. Должен ли я просто передать массив, поскольку он просто передаст ссылку на него, или я должен передать его как ref?


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

11
@ darkassassin93: передача по ссылке или по значению не зависит от того, является ли что-то ссылочным типом или типом значения. (Типы значений могут передаваться по ссылке, а ссылочные типы могут передаваться по значению.)
— LukeH,

2
В большинстве случаев, если вы можете сохранить [null] внутри поля или переменной, вы можете предположить, что это тип ссылки. Исключениями, безусловно, являются типы, допускающие значение NULL (Nullable <int> или int?), А также строки.
— Ноэль Видмер

3
@ NoëlWidmer Строки не исключение: они ссылочные типы.
— Артур Кастро

2
@ArthurCastro Argree до 50%: строки наследуются от класса, что означает, что они являются ссылочными типами. Однако их равенство основано на идентичности (сравнении значений), а не на ссылке, и их поведение при передаче переопределяется, чтобы соответствовать поведению типов значений. В основном они являются ссылочными типами по определению, но по реализации ведут себя больше как типы значений.
— Ноэль Видмер

Ответы:


201

Массивы - это механизмы, которые позволяют рассматривать несколько элементов как одну коллекцию. Microsoft® .NET Common Language Runtime (CLR) поддерживает одномерные массивы, многомерные массивы и зубчатые массивы (массивы массивов). Все типы массивов неявно являются производными от System.Array, который сам является производным от System.Object. Это означает, что все массивы всегда являются ссылочными типами, которые выделяются в управляемой куче, а переменная вашего приложения содержит ссылку на массив, а не на сам массив.

https://msdn.microsoft.com/en-us/library/bb985948.aspx


54
Типы значений наследуются от System.ValueType, который сам наследуется от System.Object. Поэтому тот факт, что Array является производным от System.Object, не означает, что это ссылочный тип. Что делает System.Array ссылочным типом, так это то, что его экземпляры копируются по ссылке. IOW, сконцентрируйтесь на том факте, что System.Array - это класс. Это то, что делает его ссылочным типом.
— P.Brian.Mackey

8
<nitpick> Я знаю, что может показаться, что документация подразумевает, что System.Array, производный от System.Object, делает его ссылочным типом. Хотя может быть неверно, что любой тип, производный от System.Object, является ссылочным типом, единственным исключением из этого правила является System.ValueType, который компилятор обрабатывает иначе. </nitpick>
— Янник Моттон,

Ссылка выше не работает. Вот еще одна ссылка на msdn,
— MUG4N 01

Все, что является производным от System.Object, является ссылочным типом, ЕСЛИ оно не является производным от System.ValueType. @ P.Brian.Mackey только потому, что тип является классом, не означает, что это ссылочный тип, потому что за кулисами структуры - это просто классы, производные от System.ValueType.
— Дэвид Клемпфнер

31

Самый простой тест для сравнения ссылочного типа и типа значения состоит в том, что ссылочные типы могут быть null, а типы значений - нет.


46
... за исключением типов значений, допускающих значение NULL, которые допускают значение NULL (вы можете установить значение NULL, что означает значение NULL для типа, а не пустую ссылку ) и по-прежнему являются типами значений.
— Джон Скит,

1
Никогда не думал об этом, когда пытался понять, являются они типами значений или нет! Отличная идея.
— пожрал элизиум


6

Сначала я хочу сказать вам, что Array - это ссылочный тип. Зачем? Я объясняю, бросьте сюда один пример.

Пример:

int val = 0; // this is a value type ok
int[] val1 = new int[20] // this is a reference type because space required to store 20 integer value that make array allocated on the heap.

Также ссылочные типы могут иметь значение NULL, а типы значений - нет.

тип значения, хранящийся в стеке, и ссылочный тип, хранящийся в куче

Вы можете передать массив в функцию, используя out или ref. Различаются только методы инициализации.

Больше..


3

Проверьте, является ли это типом ссылки или значения:

// we create a simple array of int
var a1 = new int[]{1,2,3};
// copy the array a1 to a2
var a2 = a1;
// modify the first element of a1
a1[0]=2;
// output the first element of a1 and a2
Console.WriteLine("a1:"+a1[0]); // 2
Console.WriteLine("a2:"+a2[0]); // 2
//**************************
// all the two variable point to the same array
// it's reference type!
//**************************

Вы можете протестировать это онлайн: https://dotnetfiddle.net/UWFP45


2
Было бы проще создать массив и попытаться присвоить ему значение null. Компиляция не
— удалась

Будьте предупреждены. После выпуска C # 8 он также выйдет из строя, если вы используете функцию ссылочных типов, допускающих значение NULL, поскольку ссылочные типы, не допускающие значения NULL, также не могут принимать значение NULL.
— Марк А. Донохо

2

Сам массив является ссылочным типом. Значения этого массива являются значениями или ссылочными типами, как определено типом данных массива. В вашем примере массив - это ссылочный тип, а значения - это типы значений.

Все одномерные массивы неявно реализуют IList<T>, где <T>- тип данных массива. Вместо этого вы можете использовать этот интерфейс в качестве типа данных параметра вашего метода. Вы также можете использовать IEnumerable<T>для типа данных. В любом случае (или даже если вы просто используете int[]) вам не нужно явно передавать его в качестве refпараметра.


0

// Ссылка на массив передается по значению. Отсюда и путаница :-) ...

        int[] test = { 1, 2, 3, 4 };

        modifContenuSansRef(test);
        Console.WriteLine(test[0]); // OK --> 99 le contenu du tableau est modifié

        modifTailleSansRef(test);
        Console.WriteLine(test.Length); // KO --> 4 La taille n'est pas modifiée

    }

    static void modifContenuSansRef(int[] t)
    {
        t[0] = 99;
    }

    static void modifTailleSansRef(int[] t)
    {
        Array.Resize(ref t, 8);
    }

0

Массивы всегда являются ссылочными типами. Не имеет значения, что массив будет содержать тип значения, такой как int, или ссылочный тип, такой как строка. Например, когда вы объявляете массив

int[] integers=new int[10];

Сама целочисленная переменная содержит только ссылку на массив, который будет находиться в куче.

Также многие люди упоминают, что вы можете отличать тип значения от ссылочного типа, просто в зависимости от того, что эта переменная может быть нулевой или нет. Я хотел бы упомянуть, что в C # текущие типы значений также могут быть нулевыми

например

int? integer=null

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


-2

Немного понимания:

Например, intпредставляет собой одно целое число, int[]представляет собой массив целых чисел.

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

//create a new array of 32 ints.
int[] integers = new int[32];

Все массивы являются ссылочными типами и соответствуют ссылочной семантике. Следовательно, в этом коде, несмотря на то, что отдельные элементы являются примитивными типами значений, integersмассив является ссылочным типом. Итак, если вы позже напишете:

int[] copy = integers;

это просто назначит всю копию переменной для ссылки на один и тот же массив, но не создаст новый массив.

Синтаксис массива C # является гибким, он позволяет объявлять массивы без их инициализации, чтобы впоследствии можно было динамически изменять размер массива в программе. С помощью этого метода вы в основном создаете нулевую ссылку, а затем указываете эту ссылку на динамически выделяемый участок памяти, запрошенный с newключевым словом:

int[] integers;
integers = new int[32];

Спасибо.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.