Özel mülk mü yapmalısınız?


19
private string mWhatever;

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = value;
    }
}

Özel ya da değil, her bir üye için mülk yapan bazı insanlar gördüm ... Bu bir anlam ifade ediyor mu? İçinde bulunan sınıf içindeki üyeye erişimi kontrol etmek istediğinizde, vakaların% 1'inde mantıklı olduğunu görebiliyordum çünkü her üye için özellikleri kullanmazsanız tutarsızlıklara yol açıp Üyenin erişimi var veya yok (sınıf kapsamında her ikisine de erişiminiz olduğundan).

Yanıtlar:


17

Kısa cevap: Evet , ihtiyaç olduğunda. Aksi takdirde, Otomatik Olarak Uygulanan bir Özellik alıcı ve ayarlayıcı kullanın.private string Whatever { get; set;}

  • Yakın bir alan adı yaklaşımı kullanırken çok kullanışlıdır
  • Değeri ayarlarken belirli bir mantığın kontrol edilmesi gerektiğinde de kullanışlıdır

Özel ayarlayıcıların ne zaman kullanılacağının tam açıklaması: C # özellik kullanımı .


Gerekirse mülkün daha sonra kamuya açık hale getirilmesi de gerçekten kolaydır.
Tom Pickles

4
Bir nedir yakın alan yaklaşımı ?
Trisped

1
Sınıfın bir özelliğindeki özel bir ayarlayıcıya atıfta bulunuyordum. Nesneden ayarlanan değere doğrudan erişimi engellemeli ve değeri ayarlamadan önce bir miktar mantık denetimini kolaylaştırmalıdır.
Yusubov

genel ayarlayıcı / alıcılarla özel değişkenlere sahip olma (yalnızca saf olsalar bile), kodunuz bir kütüphaneye derlenmişse, saf ayarlayıcı / alıcılarınızı yanda bulunanlarla değiştirirseniz, imzanın değişmeden kalacağı avantajı vardır. ancak bunun yerine basit bir ortak değişken kullanırsanız, kütüphane imzası, özel olmayan ayarlayıcı / alıcılarla özel olarak değiştirirseniz kütüphane imzası değişir. .. Bu, kütüphaneniz bu şekilde değişirse, kütüphanenizin tüketicilerinin yeniden derlenmesi gerektiği anlamına gelir.
orion elenzil

12

Burada bazı iyi cevaplar var, ama bence bunların çoğu sorunuzun bir noktasını kaçırıyor:

Özel ya da değil, her bir üye için mülk yapan bazı insanlar gördüm ... Bu bir anlam ifade ediyor mu?

Bence bu her üye için nadiren gerekli . İle başla

 private string Whatever;

Daha sonra bu belirli üye için kapsüllemeye veya koşullu bir kesme noktasına ihtiyaç duyduğunuz bir noktaya geldiğinizde , yine de aynı adı taşıyan bir özellikle değiştirebilirsiniz - çoğu durumda, kullanılan kodu değiştirmeden Whatever. Ancak dikkat edin, ince farklılıklar var, bu SO yazısında Brian Rasmussen'in cevabına bakın (bağlantı ayrıca Emmad Kareem, +1 tarafından verilmiştir).


+1, ayrıca,
haklısın

Bir alanı gerçeğin ardından bir mülke yeniden düzenlemek bir kabustur; tüm tüketicileri yeniden derlemenizi gerektirir. Otomatik mantığı özel mantık içerecek şekilde değiştirmek çok kolaydır. Kodun refactor'u görme şansı bile olsa, sadece başlangıçtan itibaren özellikleri kullanırsanız çok daha az iş olacaktır.
Dan

@ Dan: Çoğu projede çabanın aynı olduğunu gördüm, her iki durumda da yeniden derlemelisiniz . Bununla birlikte, özelliklerin, özellikle otomatik özelliklerin kullanılmasının, yansıma veya "değişken" parametrelerinde üye değişkenlerin kullanımıyla ilgili bazı hassas sorunların önlenmesine yardımcı olabileceğini doğru düşünüyorum.
Doc Brown

@DocBrown Her durumda, kesinlikle bir tümünü yakalama ifadesi değildir. Basit tutmak ve bir alan kullanmak için birçok neden var. Bir refactoru tahmin edebiliyorsanız, ince problemler bile dikkate değerdir.
Dan

7

Bu yaklaşımın en büyük avantajlarından biri , değişkenlerinizin ne zaman değiştiğini kontrol etmenizdir .

Aşağıdakileri göz önünde bulundur.
Büyük bir projede hata ayıklama yapıyorsunuz. Belirli bir yöntem bir istisna atar. Bir kesme noktası ayarlarsınız ve belirli bir üye değişkenin değeri yanlış olduğunu ortaya çıkarırsınız. Kodunuzun bu değişkene çok yoğun bir şekilde bağlı olduğunu ve yüzlerce yazma kullanımı bulduğunuzu varsayalım ( Spagetti senaryosu ). Yani bu kullanımlardan hangisinin kötü bir değer verdiğini anlayamazsınız .
Kod çok iş parçacıklıysa, hata ayıklama gerçek bir kabus haline gelebilir.

Özellik ile ayarlayıcıda bir kesme noktası ayarlayabilirsiniz . Bir durumla birlikte, tek bir işlemde çivilenebilir.

VC ++ veri kesme noktalarına sahiptir , ancak yalnızca yönetilmeyen kod için kullanılabilir.


1

Bir özellik kullanmıyorsanız, diğer tek seçeneğiniz değişken verileri depolamak için bir alan kullanmaktır. Özellikler ve alanlar arasında önemli farklar vardır. Bu farklılıkların çoğu Alanlar ve Özellikler arasındadır . Farklılıkları incelemenizi ve uygulama gereksinimlerinize göre seçiminizi yapmanızı öneririm. Bununla birlikte, özellikler yerine alanları kullanmanın, doğası ve eksikliğinden dolayı ortak OO uygulaması olmadığını unutmayın.


1

Özel özellikler, sınıfınıza dahil olan şeylerin davranışlarını özetlemek için çok yararlı olabilir. Özel olmaları, özelliklerin size verdiği sözdizimsel şekerden faydalanmamanız gerektiği anlamına gelmez.


Ancak verilen örnek kötüdür. Boilerplate mülk sahipleri ve bunun gibi ayarlayıcılar neredeyse her zaman kötü bir fikirdir. C # 3.0 veya üstünü kullanıyorsanız, otomatik özellikler çok daha iyi bir fikirdir:

private string Whatever { get; set; };

Bu daha kısa, daha temiz ve daha okunabilir. Aslında sadece destek değişkenini tanımlamaktan çok daha uzun değildir.

En önemlisi, otomatik özellikler, programın geri kalanının semantiğini değiştirmeden herhangi bir zamanda tam özelliklere dönüştürülebilir! Bu nedenle, doğrulama veya hata işleme eklemeniz gerekiyorsa, bunu kolayca yapabilirsiniz.


Olduğu gibi, ben her zaman bunu, (Ben bir tek okuma özelliği olamazdı yapıcı değere yazmak mümkün yalnızca zorlamak için bir utanç olduğunu düşündüm iletmenin türleri tercih ) ama bu C # 6.0 eklenmiştir olarak Aşağıdakileri yapmanızı sağlayan "Otomatik Özellik Başlatıcıları":

private string Whatever { get; } = ...;

veya

private string Whatever { get; };

ile birlikte

    Whatever = ...;

yapıcı.


0

Özel mülkler için bunu yapmak kesinlikle gerekli değildir, ancak özelliğin erişim değerini değiştirmeden temel değeri nasıl aldığını / ayarladığını değiştirmeye izin verir.

Örneğin, temel değerin nasıl ayarlandığını değiştirme:

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = string.IsNullOrEmpty(value) ? string.Empty : value;
    }
}

0

Evet

Ben şahsen önbellekleme mekanizması olarak kullanıyorum ve buna mülk düzeyinde önbellekleme diyebiliriz .

private List<User> users;
private List<User> Users
{
    get
    {
        if(users == null) users = new UserManager().GetUsers();
        return users;
    }
}

Şimdi sınıfımın diğer yerlerinde Users, usersalan yerine özellik kullanıyorum .

Başka bir uygun durum, bir alanda bir mantık uygulamak istediğinizde, ancak bir sınıfta merkezi bir şekilde olabilir. Böylece hem bir GetFoo()yöntem hem de alan Fooiçin bir özellik oluşturabilirsiniz foo.

private string foo;
private string Foo
{
    get
    {
        return "Mr. " + foo;
    }
}

0

Dikkate alınması gereken başka bir şey:

Gerçek özellikler bir uygulama detayıdır. OOP'un amaçlarından biri, mümkün olan yerlerde uygulama ayrıntılarının gösterimini en aza indirmeye çalışmaktır.

Bunun nedeni, özellikleri gizleyip yalnızca alıcılar ve ayarlayıcılar aracılığıyla göstermeniz durumunda çok daha fazla kontrole sahip olmanızdır. Örneğin, alıcınız girişini doğrulayabilir ve mülkün geçersiz bir duruma ayarlanmasını engelleyebilir. Değeri değiştirme yeteneği zaman açısından kritik ise, ayarlayıcı buna karşı da koruma sağlayabilir. Alıcı, herhangi bir nedenden dolayı gerçek değeri pahalı hale getirmelidir, tembel başlatma ve / veya önbellekleme yapabilir.

Getters ve setters maruz kalma ve özellikleri gizli bazen bir özelliğe ihtiyacınız yok demektir. Alıcı, çağırmadaki değeri hesaplayabilir veya görevi başka bir yere veya özelliklerini yerine getirmesine izin veren herhangi bir şeye yetki verebilir. Sınıfınızla ilgili önemli olan, bilginin dahili olarak nasıl temsil edildiği değil, ondan erişebileceğiniz bilgilerdir.

Tabii ki, sınıf dışındaki herhangi bir şeyin doğrudan bir mülke erişebilmesinin olumsuz sonuçları yoksa, o zaman onu herkese açık hale getirmelisiniz. Ancak tecrübelerime göre, bu tür vakalar nispeten az ve uzaktır.


0

Bunun eski bir soru olduğunu ve @Yububov'un söylediği her şeyin doğru olduğunu biliyorum , ancak ayarlayıcıdaki belirli mantık hakkındaki ikinci kurşun noktasına göre ve kimsenin özellikle bundan bahsetmediğini görmediğim için, sınıfınız mükemmel bir örnek olacaktır. INotifyPropertyChangedarayüzü uygular .

Bu, WCF ve Silverlight'ta bir ton kullanılır, bu da belirli bir özelliğin aşağıdaki sınıftaki gibi ayarlayıcısındaki mantık yoluyla ne zaman değiştiğini bilmenizi sağlar :

public class Settings : INotifyPropertyChanged
{
    public Settings() 
    { 
        this.CountryField = String.Empty; 
    }

    private string CountryField;
    public string Country
    {
        get { return this.CountryField; }
        set
        {
            if (Object.ReferenceEquals(this.CountryField, value)) { return; }

            this.CountryField = value;
            this.RaisePropertyChanged("Country");
        } 
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler propertyChanged = this.PropertyChanged;

        if (propertyChanged != null)
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
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.