SORU
29 Mayıs 2012, Salı


Nasıl dizeleri geçti .NET?

Zaman geçer string bir işlevi, bir işaretçi dize içeriğini geçti, yoksa tüm dize geçirilen işlev yığını gibi bir struct olurdu?

CEVAP
29 Mayıs 2012, Salı


Sorunuzu yanıtlamak için, şu kodu göz önünde bulundurun:

void Main()
{
    string strMain = "main";
    DoSomething(strMain);
    Console.Write(strMain); // What gets printed?
}
void DoSomething(string strLocal)
{
    strLocal = "local";
}

Burada ne olacağını tahmin etmek için bilmek ve anlamak gereken üç şey var.

  1. Dizeler C başvuru türleri#. Ama bu resmin sadece bir parçası.
  2. Ayrıca sabit, dize değiştiriyorsun gibi görünen bir şey herhangi bir zaman, değil mi. Tamamen yeni bir dize oluşturulan alır, başvuru işaret ve eskisini çöpe atmak olur.
  3. Dizeleri olmasına rağmen başvuru türleri, strMain başvuru tarafından geçirilen değil. Birbaşvuru yazınama referans ediliyordeğeri tarafından geçirilen. Bu zor bir fark var, ama önemli değil. ref anahtar olmadan bir parametre geçirmek her zaman (out parametreleri hariç), değer bir şey geçti.

Ama bu ne anlama geliyor?

Değeriyle geçirmeden başvuru türleri: zaten yapıyorsun

C veri türleri iki gruba ayrılır#:başvuru türlerivedeğer türleri. Ayrıca C parametreleri için iki yol vardır#:başvuruylavedeğer. Aynı bu ses ve kolayca karışır. Aynı şey değiller!

HERHANGİ bir parametre geçirmek ve ref anahtar kelime kullanmak istemiyorsanız, o zaman değeri ile geçtin. Eğer değer geçti, gerçekten geçti ne bir kopyası oldu. Amaeğer parametre bir başvuru türü ise, o zaman kopyalanan şey referans olduişaret değildi her neyse.

İşte Main bizim yönteminin ilk satırı:

string strMain = "main";

Aslında bu hat üzerinde yarattığımız iki şey vardır: main bellekte bir yerlerde saklı, ve bir referans değişken strMain işaret adında bir dize değeri ile.

DoSomething(strMain);

Şimdi DoSomething başvuru geçiyoruz. Değeri ile onu geçtik, bir kopyasını yaptık. Ama bir başvuru türü, başvuru, dize kendisi kopyaladık değil yani. Şimdi her bellek aynı değer için iki başvuru var.

Aranan içeride

Burada DoSomething yöntemi üst:

void DoSomething(string strLocal)

ref hiçbir kelime, her zamanki gibi. strLocal strMain değil, ama onlar aynı yere işaret de değil. Biz "değişim" strLocal bu gibi

strLocal = "local";   

...vermedikdeğiştisaklı değer aslında. Re-sivri başvuru yaptık. Başvuru strLocal adlı aldık ve yepyeni bir dize doğrulttu. Bunu yaptığımız zaman strMain ne olacak? Nothing. It's still pointing at the old string!

string strMain = "main"; //Store a string, create a reference to it
DoSomething(strMain);    //Reference gets copied, copy gets re-pointed
Console.Write(strMain);  //The original string is still "main" 

Değişmezliğini tanıdı önemlidir

Hadi bir an için senaryoyu değiştirin. Dizelerle çalışmaya değiliz, ama bazı değişken referans türü, oluşturduğunuz bir sınıf gibi düşün.

class MutableThing
{
    public int ChangeMe { get; set; }
}

Eğerizleyinbaşvuru objLocal nesneye işaret, onun özelliklerini değiştirebilirsiniz:

void DoSomething(MutableThing objLocal)
{
     objLocal.ChangeMe = 0;
} 

Hala bellekte 35 ** sadece bir tane var, ve kopyalanan referans ve orijinal referans hem de bunu gösteriyor. 44**:

void Main()
{
    var objMain = new MutableThing();
    objMain.ChangeMe = 5; 
    Console.Write(objMain.ChangeMe);  //it's 5 on objMain

    DoSomething(objMain);             //now it's 0 on objLocal
    Console.Write(objMain.ChangeMe);  //it's also 0 on objMain   
}

Ah, ama...

...dizeleri değişmez! Ayarlamak için ChangeMe özelliği yok. C-tarzı bir char dizisi ile senin gibi strLocal[3] = 'H'; yapamazsın; yepyeni bir dize yerine inşa etmek zorunda. strLocal değiştirmenin tek yolu başka bir dize de referans noktası, 41* *sen hiçbir şey yapma strMain etkileyebilir anlamına gelir. Değeri sabittir ve referans bir kopyasıdır.

Yani dizeleri başvuru türleri olmasına rağmen, değeri geçirmeden aranan arayan dize etkilemez giden ne olursa olsun anlamına gelir. Ama o zamandan beri onlarbaşvuru türleri, geçmek istediğinizde hafıza, tüm dize kopyalamak zorunda değilsiniz.

Ek kaynaklar:

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • kimaliz

    kimaliz

    18 Temmuz 2006
  • PhoneBuff

    PhoneBuff

    10 HAZİRAN 2011
  • PlayStation

    PlayStation

    16 Aralık 2005