2016-01-20 37 views
5

yılında belirleyiciler C# yapılar ve arabirimler arasında garip bir fark (bana göre) bir ortaya çıktı. Bu arayüzü ve yapı düşünün: Ben özelliği olarak bir numarası ile yeni bir sınıf oluşturduğunuzdaC# getters/yapılar ve arayüzleri

public interface INumber 
{ 
    void ChangeNumber(int n); 
    void Log(); 
} 
public struct Number : INumber 
{ 
    private int n; 
    public void ChangeNumber(int n) 
    { 
     this.n = n; 
    } 
    public void Log() 
    { 
     Console.WriteLine(this.n); 
    } 
} 

, 2'ye n değiştirebilir ve Log kullanarak numarayı yazdırmak için ChangeNumber yöntemini kullanın, bunun yerine 0 yazdırır:

public class NumberContainer 
{ 
    public Number Number { get; set; } 
    public NumberContainer() 
    { 
     this.Number = new Number(); 
     this.Number.ChangeNumber(2); 
     this.Number.Log();    //prints 0... 
    } 
} 

Bir süre sonra farkettim ki, this.Number.ChangeNumber(2);'u aradığımda, aslında yeni bir nesne (alıcıdan dolayı) oluşturuyorum ve bu sayıyı 2 olarak değiştirdim. Ama sonra Numarayı değiştirerek biraz değiştirdim. Bir MÜHENDİSLİK mülküne mülk:

public class NumberContainer 
{ 
    public INumber Number { get; set; } 
    public NumberContainer() 
    { 
     this.Number = new Number(); 
     this.Number.ChangeNumber(2); 
     this.Number.Log();    //prints 2! 
    } 
} 

Bu durumda, 2 yazdırır! Bu neden oluyor? Arabirim için aynı prensipler geçerli değil mi?

+1

Arabirim olarak başvurulduğunda kutulanır. Ama genel olarak, yapıları imtiyazlı hale getirmek en iyisidir ya da katlanılabilirliğe ihtiyacınız varsa, onu bir sınıf yapmalısınız. – juharr

cevap

4

Fark, struct'un interface (bir sınıf veya yapı tarafından gerçekleştirilebilen) bir referans türü olarak kullanılmasıdır. sizin örnekte büyük bir fark yaratıyor

. İlk durumda yaptığınız şey, this.Number numaralı telefona "Bana sayının değerini al" anlamına gelir. Bu, yığındaki değeri çektiği ve herhangi bir yerde saklanmayan yığındaki (adlandırılmamış) değişkenin değiştirildiği anlamına gelir. Diğer durumda

, arayüz referans türüdür - yani, kendi adresine depolanır ne olursa olsun alır ve onu değiştirir.

Genellikle ben sahip önermek olmaz bir değişken (zaten yorumlarda belirtildiği gibi) struct.

Sen mesela bu konu hakkında daha fazla bilgi bulabilirsiniz Why are mutable structs “evil”?

2

Bu, NumberContainer sınıfındaki otomatik özellikten kaynaklanıyorsa, mülkünüze erişirken daima bir değerin kopyasını edinebilirsiniz. Eğer bir alana özelliğini değiştirirseniz beklendiği gibi

işe yarıyor. Otomatik işleyişin yalnızca bir çift yöntem olduğunu ve bu değer türlerinin herhangi bir yönteme döndüğünüzde/iletildiğinde kopyalandığını unutmayın.

Eğer aslında aradığınız

 this.Number.ChangeNumber(2); 
     this.Number.Log();    //prints 0... 

aradığınız:

this.getNumber() // returns copy of value type 
     .ChangeNumber(2); // executes op on that copy 

    this.getNumber() 
     .Log(); 

Eğer operasyonlar hep aynı nesne üzerinde gerçekleştirilir böylece, bir nesneye başvuru dönüyor arayüzünü kullanıyor.