Чи є int [] тип посилання чи тип значення?


124

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


11
Надалі ви можете перевірити, чи передається щось за посиланням або за значенням, створивши змінну, передавши цю змінну в метод, що змінює цю змінну, і перевірити, яке значення має ця змінна після її запуску через метод. Якщо це те саме, його передається за значенням, інше, передається посиланням.

11
@ darkassassin93: Перехід за посиланням або за значенням не пов'язаний з тим, чи є щось посилальним типом чи типом значення. (Типи значень можна передавати за посиланням, а типи посилань можна передавати за значенням.)
ЛукаХ

2
У більшості випадків, якщо ви можете зберегти [null] всередині поля чи змінної, ви можете припустити, що це тип ref. Винятками, безумовно, є нульові типи (Nullable <int> або int?), А також рядки.
Ноель Відмер

3
@ NoëlWidmer Strings не є винятком: вони посилання типів.
Артур Кастро

2
@ArthurCastro Погодитися до 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>
Yannick Motton,

Посилання вище перервано. Ось ще посилання msdn, яке показує ієрархію успадкування System.Array: msdn.microsoft.com/de-de/library/system.array(v=vs.110).aspx
MUG4N

Все, що походить від System.Object, є еталонним типом, без цього воно також походить від System.ValueType. @ P.Brian.Mackey тільки тому, що тип - це клас, не означає, що це еталонний тип, тому що поза кадром структури - це просто класи, що походять від System.ValueType.
Девід Клемффнер

31

Найпростіший тест на тип посилання проти типу значення полягає в тому, що типи посилань можуть бути null, але типи значень не можуть.


46
... крім обнуляє типів значень, які обнуляти (ви можете встановити значення NULL, що означає нульове значення для типу , а не нульова посилання ) і до сих пір типів значень.
Джон Скіт

1
Ніколи не думав робити це, намагаючись зрозуміти, чи є вони типовими значеннями чи ні! Чудова ідея.
пожирав елізіум


6

Спершу хочу сказати вам, що масив - це еталонний тип. Чому? Я пояснюю, що тут кидаю один приклад.

Приклад:

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.

Також типи посилань можуть бути недійсними, тоді як типи значень не можуть.

тип значення, що зберігається в Stack, а тип посилання, що зберігається в Heap

Ви можете передати масив для функціонування за допомогою або виправлення. Тільки методи ініціалізації різні.

більше ..


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
Просто було б простіше створити масив і спробувати призначити його нульовим. Компіляція не змогла б, якби це значення типу ..
пожирав elysium

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

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

Масиви завжди є посиланнями type.it не має значення масив буде містити тип значень, наприклад int або тип посилання, наприклад string.When ви оголошуєте масив, наприклад

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.