C # 3.0 otomatik özellikleri - yararlı ya da değil? [kapalı]


155

Not: Bu C # başladığımda gönderildi. 2014 bilgisiyle, otomatik özelliklerin C # dilinin başına gelmiş en iyi şeyler arasında olduğunu söyleyebilirim.

Özel ve ortak bir alan kullanarak C # özellikleri oluşturmak için kullanılır:

private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Şimdi, .NET 3.0 ile otomatik özellikler aldık:

public string Title { get; set; }

Bunun daha felsefi / sübjektif sorular olduğunu biliyorum, ancak her alan için beş satır kod kaydetme dışında bu otomatik özellikleri kullanmak için herhangi bir neden var mı? Benim kişisel yakınlığım, bu özelliklerin benden bir şeyler saklaması ve kara büyünün büyük bir hayranı değilim.

Aslında, gizli özel alan hata ayıklayıcıda bile görünmez, bu da get / set işlevlerinin hiçbir şey yapmadığı göz önüne alındığında tamamdır. Ama aslında bazı alıcı / ayarlayıcı mantığını uygulamak istediğimde, özel / ortak çifti yine de kullanmalıyım.

Daha sonra alıcı / ayarlayıcı mantığını değiştirme yeteneğini kaybetmeden kod çok (bir vs altı satır) kaydetmek yarar görüyorum, ama sonra tekrar ben zaten sadece bir ortak alan "Genel dize Başlık" bildirerek yapabilirim {get; Ayarlamak; } böylece daha fazla kod tasarrufu sağlar.

Peki, burada ne eksik? Neden birisi otomatik özellikleri kullanmak isteyesin ki?


86
"Kişisel yakınlığım, bu özelliklerin benden bir şeyler saklaması ve ben kara büyünün büyük bir hayranı değilim." Ha? Derleyicinin her zaman bir ton sakladığını biliyorsun, değil mi? Montaj yazmıyorsanız (veya daha doğru bir şekilde, kodunuz için gerçek 1'ler ve 0'lar), yazdığınız her şey sizden bir şeyler saklıyor.
Charles Boyung

Yanıtlar:



62

Evet, sadece kod tasarrufu sağlar. Çok fazla yüklediğinizde okumak çok daha kolay. Yazması daha hızlı ve bakımı daha kolaydır. Kod kaydetmek her zaman iyi bir hedeftir.

Farklı kapsamlar ayarlayabilirsiniz:

public string PropertyName { get; private set; }

Böylece özellik sadece sınıf içinde değiştirilebilir. Özel ayarlayıcıya yansıma yoluyla erişebildiğiniz için bu gerçekten değişmez değil.

C # 6'dan itibaren gerçek readonlyözellikler de oluşturabilirsiniz - yani yapıcı dışında değiştirilemeyen değişmez özellikler:

public string PropertyName { get; }

public MyClass() { this.PropertyName = "whatever"; }

Derleme zamanında:

readonly string pName;
public string PropertyName { get { return this.pName; } }

public MyClass() { this.pName = "whatever"; }

Çok sayıda üyesi olan değişmez sınıflarda bu çok fazla kod tasarrufu sağlar.


"Yani hiçbir işlevi kaybetmezsiniz." Onları nasıl ayıklarsın?
wal

2
@wal - hata ayıklamak için ne var? Bu açıdan temelde üye değişkenlerle ilgileniyorsunuz.
Keith

6
@wal - Onlara bir kesme noktası koyabilirsiniz, tıpkı bir üye değişkenine erişebildiğiniz gibi, bunlara adım atamazsınız. ama neden isteyesin? Otomatik özelliklerin gerçekte yaptığı şey hem önemsiz hem de otomatik olarak oluşturulmuştur, hataların olması muhtemel olmayan tek bir yer varsa.
Keith

3
bunu Keith'in dışına çıkarmamız gerekebilir. :)
wal

1
Ama tamam, myObj.Title için birçok ayarlayıcı çağrınız olduğunu varsayalım ... değerin "metin" ten null değerine, yani koşullu bir kesme noktasına değiştiğini görmek istiyorsunuz. bunu nasıl başarıyorsun? setter üzerinde bir kırılma noktası bile kuramazsınız
wal

45

Özellikler yerine alanları kullanmanın üç büyük dezavantajı:

  1. Bir alana veri atamazsınız, bir mülke
  2. Bir alanı kullanmaya başlarsanız, daha sonra (kolayca) bunları bir mülke değiştiremezsiniz
  3. Bir alana ekleyemediğiniz bir özelliğe ekleyebileceğiniz bazı özellikler var

7
"Bir alanı kullanmaya başlarsanız, daha sonra (kolayca) bunları bir mülke değiştiremezsiniz", üzgünüm ama neden?
Homam

6
@Homam Genel olarak, alanlarınızda yansıma kullanan herhangi bir tüketici kodu, FieldInfo kullanmaktan PropertyInfo'ya geçmek zorunda oldukları için bozulacaktır.
WCWedin

8
@Homam Ayrıca, bir alanı bir mülk olarak değiştirmek, ikili uyumluluğunu bozarak alanın tüm tüketicilerinin yeniden derlenmesini gerektirir.
Odrade

1
yeniden derleme ve yansıma sorunları bir yana, Visual Studio kullanarak alanları kapsüllemek çok kolaydır: Ctrl-R + E, bir alanı uygun alıcılar / ayarlayıcılarla bir özelliğe dönüştürmenize izin verir. (veya alanı sağ tıklayın, yeniden çarpan, kapsülleme alanı).
JoeBrockhaus

@Hommam alanları değerlerdir (değişkenlerdir) ve özellikler değildir. Bir alan olduğunda derlenmiş olabilecek şeyler, bir mülk olduğunda olmayabilir.
Mark

29

Ben şahsen oto-özellikleri seviyorum. Kod satırlarını kaydetmenin nesi yanlış? Alıcılarda veya ayarlayıcılarda bir şeyler yapmak istiyorsanız, bunları daha sonra normal özelliklere dönüştürmek için sorun yoktur.

Dediğiniz gibi alanları kullanabilirsiniz ve bu alanlara daha sonra mantık eklemek isterseniz, bunları özelliklere dönüştürürdünüz. Ancak bu, herhangi bir yansıma kullanımı (ve muhtemelen başka bir yerde?) İle ilgili sorunlar yaratabilir.

Ayrıca özellikler, alanla yapamayacağınız alıcı ve ayarlayıcı için farklı erişim düzeyleri ayarlamanıza olanak tanır.

Sanırım var anahtar kelimesi ile aynı. Kişisel tercih meselesi.


29

C ++ yaratıcısı Bjarne Stroustrup'tan:

Özellikle birçok get ve set fonksiyonuna sahip sınıflardan hoşlanmıyorum. Bu genellikle ilk etapta bir sınıf olmaması gerektiğinin bir göstergesidir. Bu sadece bir veri yapısı. Ve eğer gerçekten bir veri yapısı ise, onu bir veri yapısı yapın.

Ve biliyor musun? O haklı. Özel alanları bir get ve set içinde, ne zaman get / set içinde hiçbir şey yapmadan basitçe sararsınız, çünkü bunun yapılması "nesne odaklı" bir şeydir. Bu Microsoft'un soruna çözümü; bunlar temel olarak bağlanabileceğiniz genel alanlardır.


2
Bunun daha fazla puan olması gerektiğini düşünüyorum. Çok fazla insan, oto mülkleri, yüceltilmiş bir kamusal alandan biraz daha fazla olan korkunç kapsüllenmiş (ya da hiç kapsüllenmemiş) sınıflar yazmak için yeşil ışık olarak görüyor. Elbette bu, insanların aracın kendisinden ziyade aracı nasıl kullandıklarıyla ilgili bir konudur, ancak genel olarak özellikleri tartışırken bahsetmenin önemli olduğunu düşünüyorum.
sara

18

Kimsenin bahsetmediği bir şey, oto-özelliklerin maalesef değişmez nesneler (genellikle değişmez yapılar) için ne kadar yararlı olmadığıdır. Çünkü bunun için gerçekten yapmanız gerekenler:

private readonly string title;
public string Title
{
    get { return this.title; }
}

(alan, yapıcıda geçirilen bir parametre aracılığıyla başlatılır ve sonra salt okunurdur.)

Yani bunun basit get/ otomatik private setpilotlara göre avantajları vardır .


Herhangi bir özelliği değiştiren bir yapınız varsa, yeni bir yapı ile sonuçlanır. Bu sadece dahili olarak değiştirilemez bir referans türü isteseniz bir sorun olurdu - neden birine ihtiyaç duymanızın bir nedenini göremiyorum.
Keith

@ Keith: İlk cümleniz aslında yanlış görünüyor.
Domenic

3
Olmaz mıydı public string Title { get; private set; }tür sonucu tamamen aynı şeyin içinde? O zaman tabii ki sınıfın içinden değiştirebilirsin, ama bunu yaparsan başka problemlerin var ...: p
Svish

2
@Svish - bu argümanla C # 'daki salt okunur anahtar kelime asla kullanılmamalıdır çünkü kullanımı bu "farklı sorunları" gizlediğimiz anlamına gelecektir
Zaid Masud

2
Demek istediğim, dış API türünden bakıldığında çok fazla fark yaratmayacak. Ve böylece, otomatik özellikler istenirse kullanılabilir. En iyi şey tabii ki böyle bir şey yapabilseydiniz olurdupublic string Title { get; private readonly set; }
Svish

12

Arabirim tanımındaki özellikleri kullanabileceğiniz, arabirim tanımındaki ortak alanları kullanamayacağınız için her zaman ortak alanlar yerine özellikler oluşturuyorum.


8

Otomatik özellikler, C # 'da herhangi bir şey kadar kara bir sihirdir. Bir kez normal bir C # özelliğine genişletilmesi yerine IL'ye derleme açısından düşündüğünüzde, öncelikle diğer birçok dil yapısından çok daha az kara büyü.


5

Her zaman otomatik özellikler kullanıyorum. C # 3'ten önce tüm yazımlardan rahatsız olamadım ve bunun yerine genel değişkenler kullandım.

Özlediğim tek şey bunu yapabilmek:

public string Name = "DefaultName";

Varsayılanları özellikleri olan yapıcılarınıza kaydırmanız gerekir. sıkıcı :-(


4
C # 6'daki Otomatik özellik başlatıcıları ile yakında bunu yapabilirsiniz: public string Name { get; set; } = "DefaultName"; blogs.msdn.com/b/csharpfaq/archive/2014/11/20/…
Carlos Muñoz

5

Ben sezgisel ve kod satırlarını azaltır herhangi bir yapı büyük bir artı olduğunu düşünüyorum.

Bu tür özellikler Ruby gibi dilleri bu kadar güçlü kılan özelliklerdir (bu ve aşırı özellikler azaltılmasına yardımcı olan dinamik özellikler).

Ruby tüm bunları şöyle sürdürdü:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter

2

Onlarla ilgili tek sorun, yeterince ilerlememeleri. Otomatik özellikleri ekleyen derleyicinin aynı sürümü, kısmi yöntemler ekledi. Neden ikisini bir araya getirmediler beni aştı. Basit bir "kısmi Açık <MülkAdı> Değişti", bu şeyleri gerçekten gerçekten yararlı hale getirirdi.


Başka bir yöntemin içine birden fazla kısmi yöntem koyabilirsiniz. Onlar için bir çeşit otomatik kalıp oluşturmak kafa karıştırıcı olacaktır.
Matthew Whited

2

Çok basit, kısa ve tesisin gövdesinde bir yerde gerçek bir uygulama oluşturmak istiyorsanız, türünüzün dış arayüzünü bozmaz.

Kadar basit.


1

Burada not edilmesi gereken bir şey, benim anlayışım için, bu sadece C # 3.0 ucundaki sözdizimsel şeker, yani derleyici tarafından üretilen IL aynıdır. Kara büyüden kaçınmayı kabul ediyorum, ama aynı şey için aynı, daha az satır genellikle iyi bir şeydir.


1

Bence, genel alanlar yerine her zaman otomatik özellikler kullanmalısınız. Bununla birlikte, bir uzlaşma:

Bir mülk için kullanacağınız adlandırma kuralını kullanarak dahili bir alanla başlayın . İlkini sen ne zaman

  • montaj alanının dışından alana erişmesi veya
  • alıcıya / ayarlayıcıya mantık eklemeniz gerekir

Bunu yap:

  1. alanı yeniden adlandır
  2. onu özel yap
  3. halka açık bir mülk ekle

İstemci kodunuzun değiştirilmesi gerekmez.

Bir gün, sisteminiz büyüyecek ve onu ayrı montajlara ve çoklu çözümlere ayıracaksınız. Bu durumda, Jeff'in belirttiği gibi, ortak bir alanı genel bir mülke dönüştürmek bir API değişikliği olduğu için, maruz kalan alanlar sizi rahatsız edecek şekilde geri gelecektir .


0

CodeRush kullanıyorum, otomatik özelliklerden daha hızlı.

Bunu yapmak için:

 private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Toplam sekiz tuş vuruşu gerektirir.


5
CTRL ve V tuşlarını basılı tutarsam, çok / çok şeyi yapıştırabilirim, / gerçekten hızlı bir şekilde /, ama bu 'daha iyi' olmaz. Bu asıl soruya nasıl cevap veriyor?
JBRWilkinson

0

Kod parçacıkları ile aynı ada sahip bir otomatik özellik toplamda yedi tuş vuruşudur;)


0

@Domenic: Anlamıyorum .. Bunu otomatik özelliklerle yapamaz mısın ?:

public string Title { get; }

veya

public string Title { get; private set; }

Bahsettiğiniz bu mu?


Yapabilirsiniz (ikincisi; birincisi derlenmeyecektir), ancak daha sonra alan nesnenizin içinde değişmez değildir.
Domenic

Dikkatli olun, sadece yapılar salt okunur olarak işaretlendiğinde değişmezdir, sınıflar atanamaz.
Guvante

0

Otomatik özelliklere sahip en büyük tutkum, zamandan tasarruf etmek için tasarlandıkları, ancak daha sonra onları tam gelişmiş özelliklere genişletmem gerektiğine inanıyorum.

VS2008 eksik olan bir Explode Auto-Property refactor olduğunu.

Biz işin doğrusunu kapsülü alan Refactor sadece kamu alanlarını kullanmak daha hızlı bir yol Ben iş yapar.

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.