İnt [] bir başvuru türü mü yoksa bir değer türü mü?


124

İnt'in bir değer türü olduğunu biliyorum, ancak değer türü dizileri nelerdir? Referans türleri? Değer türleri? Bir şeyi kontrol etmek için bir diziyi işleve geçirmek istiyorum. Diziyi sadece referansını geçeceği için geçmeli miyim yoksa ref olarak mı geçmeliyim?


11
Gelecekte, bir değişken oluşturarak, bu değişkeni o değişkeni değiştiren bir yönteme geçirerek ve bu değişkenin değerinin, yöntem boyunca çalıştırıldıktan sonra ne olduğunu kontrol ederek bir şeyin referansla mı yoksa değere göre mi geçirildiğini kontrol edebilirsiniz. Aynıysa, değere göre geçirilir, farklıdır, referansla aktarılır.

11
@ darkassassin93: Referansla veya değere göre geçiş, bir şeyin referans türü veya değer türü olup olmadığı ile ilgisizdir. (Değer türleri başvuru ile geçirilebilir ve başvuru türleri değere göre geçirilebilir.)
LukeH

2
Çoğu durumda, [null] değerini bir alan veya değişken içinde saklayabiliyorsanız, bunun bir ref türü olduğunu varsayabilirsiniz. İstisnalar kesinlikle null yapılabilir türler (Nullable <int> veya int?) Ve dizelerdir.
Noel Widmer

3
@ NoëlWidmer Strings bir istisna değildir: ref türleridir.
Arthur Castro

2
@ArthurCastro Argree -% 50: dizeler sınıftan miras alır, bu da referans tür oldukları anlamına gelir. Bununla birlikte, eşitlikleri referanstan ziyade kimliğe (değer karşılaştırması) dayalıdır ve geçiş davranışları, değer türlerinin davranışıyla eşleşecek şekilde geçersiz kılınır. Temelde bunlar tanım gereği referans türleridir, ancak uygulamaya göre daha çok değer türleri gibi davranırlar.
Noel Widmer

Yanıtlar:


201

Diziler, birkaç öğeyi tek bir koleksiyon olarak değerlendirmenize izin veren mekanizmalardır. Microsoft® .NET Ortak Dil Çalışma Zamanı (CLR), tek boyutlu dizileri, çok boyutlu dizileri ve pürüzlü dizileri (dizi dizileri) destekler. Tüm dizi türleri, kendisi System.Object'ten türetilen System.Array'den dolaylı olarak türetilir. Bu, tüm dizilerin her zaman yönetilen yığın üzerinde tahsis edilen referans türler olduğu ve uygulamanızın değişkeninin dizinin kendisine değil diziye bir başvuru içerdiği anlamına gelir.

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


54
Değer türleri, System.Object öğesinden miras alınan System.ValueType öğesinden miras alır. Dolayısıyla, Array'in System.Object'ten türetilmesi onun bir başvuru türü olduğu anlamına gelmez. System.Array'i bir başvuru türü yapan şey, örneklerinin başvuruya göre kopyalanmasıdır. IOW, System.Array'in bir sınıf olduğu gerçeğine odaklanın. Onu bir referans türü yapan da budur.
P.Brian.Mackey

8
<nitpick> Belgelerin System.Object'ten türetilen System.Array'in onu bir başvuru türü haline getirdiğini ima ediyor gibi görünebileceğini biliyorum. System.Object'ten türetilen herhangi bir türün bir başvuru türü olduğu doğru olmasa da, bu kuralın tek istisnası, derleyici tarafından farklı şekilde ele alınan
System.ValueType'tır

Yukarıdaki bağlantı koptu. İşte System.Array'in miras hiyerarşisini gösteren başka bir msdn bağlantısı: msdn.microsoft.com/de-de/library/system.array(v=vs.110).aspx
MUG4N

System.Object öğesinden türetilen her şey bir başvuru türüdür, ayrıca System.ValueType öğesinden de türetilmediği sürece. @ P.Brian.Mackey, bir türün bir sınıf olması, bunun bir başvuru türü olduğu anlamına gelmez, çünkü perde arkasında, yapılar yalnızca System.ValueType'tan türetilen sınıflardır.
David Klempfner

31

Referans türüne karşı değer türüne yönelik en basit test, başvuru türlerinin olabileceği null, ancak değer türlerinin yapamayacağıdır.


47
... null yapılabilir değer türleri hariç (değeri null olarak ayarlayabilirsiniz, bu, null başvuru yerine tür için boş değer anlamına gelir ) ve hala değer türleridir.
Jon Skeet

1
Değer türü olup olmadıklarını anlamaya çalışırken bunu yapmayı asla düşünmedim! İyi fikir.
elysium yiyip


6

Öncelikle Array'in bir referans türü olduğunu söylemek istiyorum. Neden? Buraya bir örnek vermeyi açıklıyorum.

Misal:

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.

Ayrıca başvuru türleri boş olabilirken değer türleri olamaz.

Yığın'da depolanan değer türü ve Yığın'da depolanan başvuru türü

Out veya ref kullanarak diziyi işleve geçirebilirsiniz. Yalnızca başlatma yöntemleri farklıdır.

Daha..


3

Bunun bir referans veya değer türü olup olmadığını doğrulamak için test edin:

// 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!
//**************************

Çevrimiçi olarak test edebilirsiniz: https://dotnetfiddle.net/UWFP45


2
Bir dizi oluşturmak ve onu null olarak atamayı denemek daha kolay olurdu. Bir değer türü olsaydı derleme başarısız olurdu ..
elysium

Önceden uyarılmalıdır. C # 8 yayınlandıktan sonra, null atanabilen başvuru türleri de null kabul edemediğinden null atanabilir başvuru türleri özelliğini kullanıyorsanız başarısız olur.
Mark A. Donohoe

2

Dizinin kendisi bir başvuru türüdür. Bu dizinin değerleri, dizi veri türüne göre belirlenen değer veya başvuru türleridir. Örneğinizde, dizi bir başvuru türüdür ve değerler değer türleridir.

Tüm tek boyutlu diziler örtük olarak uygulanır IList<T>; burada <T>dizinin veri türü bulunur. Bunun yerine, bu arayüzü yöntem parametrenizin veri türü olarak kullanabilirsiniz. IEnumerable<T>Veri türü için de kullanabilirsiniz . Her iki durumda da (veya sadece kullanıyor olsanız bile int[]) bunu bir refparametre olarak açık bir şekilde iletmeniz gerekmez .


0

// Diziye referans değer ile aktarılır. Bu karışıklığın kaynağı :-) ...

        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

Diziler her zaman başvuru türleridir. Önemli değil dizi int gibi değer türü veya dizge gibi başvuru türü içerir. Örneğin dizi bildirdiğinizde

int[] integers=new int[10];

tamsayılar değişkeninin kendisi yalnızca öbek içinde yer alacak diziye başvuru içerir.

Ayrıca birçok insan, değer türünü referans türünden ayırabileceğinizi, yalnızca değişkenin boş olabileceği veya olamayacağı gerçeğine bağlı olarak söyleyebileceğini söyler. Şunu belirtmek isterim ki c # şu anda değer türleri de boş olabilir

Örneğin

int? integer=null

ve türün referans olduğunu belirlemenin iyi bir yolu değildir veya değer yalnızca olguya bağlıdır, boş olabilir veya olmayabilir.


-2

Biraz bilgi:

Örneğin, inttek bir tamsayıyı int[]temsil eder, bir tamsayı dizisini temsil eder.

Diziyi belirli boyutlarla başlatmak için new, boyutu köşeli parantez içinde tür adından sonra vererek anahtar kelimeyi kullanabilirsiniz :

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

Tüm diziler başvuru türleridir ve başvuru semantiğini takip eder. Bu nedenle, bu kodda, tek tek öğeler ilkel değer türleri olsa bile integersdizi bir başvuru türüdür. Yani daha sonra yazarsan:

int[] copy = integers;

bu basitçe tüm değişken kopyasını aynı diziye atayacaktır, yeni bir dizi yaratmayacaktır.

C # 'ın dizi sözdizimi esnektir, dizileri başlatmadan bildirmenize izin verir, böylece dizi programda daha sonra dinamik olarak boyutlandırılabilir. Bu teknikle, temel olarak boş bir referans oluşturuyorsunuz ve daha sonra bu referansı bir newanahtar kelime ile istenen dinamik olarak tahsis edilmiş bellek konumlarına işaret ediyorsunuz :

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

Teşekkür ederim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.