Ortak Alanlar ve Otomatik Özellikler


353

Sıklıkla, alanları dış dünyaya göstermek yerine, sınıf alanları için alıcı ve ayarlayıcı yöntemleri (C #'daki özellikler) yaparak kapsüllemeyi korumamız gerektiği söylenir.

Ancak, bir alanın bir değeri tutmak için orada olduğu ve almak veya ayarlamak için herhangi bir hesaplama gerektirmediği birçok kez vardır. Bunlar için hepimiz bu sayıyı yaparız:

public class Book
{
    private string _title;

    public string Title
    {
          get{ return _title;  }
          set{ _title = value; }
    }
}

Bir itirafım var, tüm bunları yazmaya dayanamadım (gerçekten, yazmak zorunda değildi, bakmak zorundaydı), bu yüzden haydut gittim ve kamu alanları kullandım.

Daha sonra C # 3.0 geliyor ve otomatik özellikler eklediklerini görüyorum:

public class Book
{
    public string Title {get; set;} 
}

hangisi daha düzenli ve minnettarım, ama gerçekten, sadece kamusal alan yapmaktan çok farklı olan nedir?

public class Book
{
    public string Title;
}


6
Setter üzerinde bir kırılma noktası ayarlayabilmem için bir özelliği bir mülke dönüştürdüm
Ian Ringrose

1
Özel bir mülk olmayan bir şey yapmaya eğilimliyim çünkü bir araziyi bir mülke dönüştürmek zorunda olduğumu fark etmek, bazı gereksiz baş ağrısına yol açtı. Özellikler, alanlar ve yöntemler. Aman! beni geçmişte ısırmış bir uyumsuzluk diyor.
Steven Wexler

2
propKod parçacığı hızlı özelliklerinin oluşturmayı kolaylaştırır. Sadece propsekmeyi yazın.
Tono Nam

Yanıtlar:


175

Bir süre önce ilgili bir soruda , Jeff'in blogunda bazı farklılıkları açıklayan bir gönderi bağlantısı vardı.

Özellikler ve Genel Değişkenler

  • Yansıma, değişkenler ve özellikler üzerinde farklı çalışır, bu nedenle yansımayı kullanırsanız, tüm özellikleri kullanmak daha kolaydır.
  • Bir değişkene karşı veri kaydedemezsiniz.
  • Bir değişkeni bir özelliğe dönüştürmek, bir değişikliktir. Örneğin:

    TryGetTitle(out book.Title); // requires a variable

24
Msgstr "Bir değişkeni bir özelliğe değiştirmek, kırılan bir değişikliktir." Çoğu geliştirici olan yeniden kullanılabilir kütüphane, yazarken Bu tabii geçerlidir değil yapıyor.
Steven

30
Ayrıca, alanlar, otomatik özellikler bile, sanal olabilir. Dolayısıyla, bir temel sınıf, bir otomatik destek için derleyici tarafından üretilen basit bir destek alanı uygulamasına sahipken, türetilmiş sınıflar ek doğrulama veya diğer mantık / hesaplamalar gerçekleştirebilir.
KeithS

28
Ayrıca alan bir değişkendir ve başvuru ( refveya outanahtar kelime) ile iletilebilirken , bir özellik bir çift erişimcidir ve başvuru ile iletilemez. Örneğin, bool success = TryGetMyTitle(out myBook.Title);hangi kullanımlar outbir alanla ve bir özellikle çalışmaz. Bu, tarladan mülke değişimin neden kırıcı bir değişiklik olduğunun açık bir örneğidir!
Jeppe Stig Nielsen

2
@KyleBaran Hayır, bu bir anlam ifade etmiyor çünkü bir özellik bir değişken değil bir çift erişimci yöntemidir. Yapılacak olağan bir şey, yerel bir değişkeni bildirmek (büyük olasılıkla özelliği yerel değişkene bir put koymak), yerel değişkeni ref/ olarak iletmek outve daha sonra özelliği yerel değişkenin sahip olduğu değere ayarlamaktır. Ancak sonra çağrılan yöntemin kendisi özelliğe erişmez, orada yaptığınız yerel değişkene erişir.
Jeppe Stig Nielsen

5
@theberserker Doğru, ancak C # 6'da yapabilirsiniz, ancak bunu public int Foo { get; }salt okunur bir alana sahip bir otomatik özellik oluşturacaktır.
Michael Stum

83

API sorunlarını göz ardı ederek, bir özelliği kullanma konusunda en değerli bulduğum şey hata ayıklama.

CLR hata ayıklayıcı veri kesme noktalarını desteklemez (çoğu yerel hata ayıklayıcı bunu yapar). Bu nedenle, sınıftaki belirli bir alanın okunması veya yazılması için bir kırılma noktası ayarlamak mümkün değildir. Bu, bazı hata ayıklama senaryolarında çok sınırlayıcıdır.

Özellikler çok ince yöntemler olarak uygulandığından, değerlerinin okunması ve yazılması için kesme noktaları ayarlamak mümkündür. Bu onlara tarlalar üzerinde büyük bir bacak verir.


2
On yıl sonra, en azından .NET Core için veri kesme noktaları var :)
Luaan

72

Bir alandan mülke geçmek sözleşmeyi ihlal eder (örn. Tüm referans kodlarının yeniden derlenmesini gerektirir). Dolayısıyla, diğer sınıflarla (genel olarak korunan) herhangi bir üye ile bir etkileşim noktanız olduğunda, gelecekteki büyümeyi planlamak istersiniz. Bunu her zaman özellikleri kullanarak yapın.

Bugün bir oto mülk yapmak için hiçbir şey yok ve 3 ay boyunca, tembel yüklü hale getirmek istediğinizi fark edip alıcıya boş bir kontrol yapın. Bir alan kullandıysanız, bu, montajlarınıza kimlerin ve başka nelere bağlı olduğuna bağlı olarak en iyi ihtimalle yeniden derleme ve en kötü ihtimalle imkansızdır.


9
Bu cevabı beğendim çünkü 'yansıma', 'arayüz' veya 'geçersiz kılma' kelimelerini kullanmıyor. ('sözleşme' hakkında çok kötü)

65

Hiç kimse bundan bahsetmediği için: Arabirimlerdeki alanları tanımlayamazsınız. Bu nedenle, özellikleri tanımlayan belirli bir arabirim uygulamanız gerekiyorsa, otomatik özellikler bazen gerçekten güzel bir özelliktir.


1
Özellikleri tanımlayan bir arayüze ihtiyacınız varsa, soyut bir sınıf olması gerektiğini söyleyebilirim. C # arabirimlerdeki özellikleri tanımlamanıza izin verdiği için bunları kullanmanız gerektiği anlamına gelmez. Kötü tasarım.
Odys

8
@odyodyodys - Bunun kötü tasarım olduğunu kabul ettiğimden emin değilim. Lütfen gerekçenizi açıklayınız.
Zaid Mesud

4
@odyodyodys Katılıyorum zooone9243: Imp, tasarım açısından, bir mülk beyan etmek ve bir alıcı / ayarlayıcı çifti (arayüzler için yaygın bir uygulamadır) beyan etmek arasında hiçbir fark yoktur.
MartinStettner

22
@ zooone9243, + MartinStettner: Bu 6 ay önceydi, o zamandan beri çok şey öğrendim. Geri alıyorum :)
Odys

47

Genellikle gözden kaçan ve başka bir cevapta belirtilmeyen büyük bir fark: geçersiz kılma . Ortak üye alanları için aynısını yapamazken özellikleri sanal olarak bildirebilir ve geçersiz kılabilirsiniz.


10

Her şey sürüm oluşturma ve API istikrarı ile ilgilidir. Sürüm 1'de bir fark yoktur - ancak daha sonra, bunu sürüm 2'de bir tür hata kontrolüne sahip bir özellik yapmaya karar verirseniz, API'nız hiçbir kod değişikliğini değiştirmek zorunda değilsiniz. mülkiyet tanımı.


10

Otomatik olarak uygulanan özelliklerin ortak alanlara göre bir diğer avantajı, set erişimcilerini özel veya korumalı hale getirebilmenizdir ve tanımlandığı nesnelerin sınıfını ortak alanlardan daha iyi kontrol olarak tanımlamanızdır.


8

Tarla yapmakta yanlış bir şey yok public. Ancak getter/setter, privatealanlarla oluşturmanın kapsülleme olmadığını unutmayın . IMO, a'nın diğer özellikleri ile ilgilenmiyorsanız Property, bunu da yapabilirsiniz public.


1

Daha sonra başlığın benzersiz olup olmadığını kontrol etmeye karar verirseniz, bir koleksiyon veya veritabanıyla karşılaştırarak, buna bağlı herhangi bir kodu değiştirmeden bunu mülkte yapabilirsiniz.

Sadece genel bir özellik ile giderseniz daha az esnekliğe sahip olacaksınız.

Sözleşmeyi bozmadan ekstra esneklik, mülkleri kullanma konusunda benim için en önemli şeydir ve aslında esnekliğe ihtiyacım olana kadar otomatik oluşturma en mantıklıdır.


0

Tüm kod ve test nedenlerinin yanı sıra çok yararlı bulduğum bir şey, bir alan vs bir özellik ise Visual Studio IDE bir özellik değil, bir alan için başvuruları gösterir olmasıdır.


0

Benim pov sonra bazı araştırmalar yaptı

  1. Doğrulama.
  2. Bir özelliğin davranışını değiştirmek için erişimcinin geçersiz kılınmasına izin ver.
  3. Hata ayıklama amacı. Erişimcide bir kesme noktası ayarlayarak mülkün ne zaman ve neyin değiştiğini öğrenebiliriz.
  4. Yalnızca ayarlanmış bir alanımız olabilir. Örneğin, herkese açık set () ve private get (). Kamusal alanda bu mümkün değildir.

Bize daha fazla olanak ve genişletilebilirlik sağlıyor.

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.