Değişmezliği garanti etmek, bir mülk yerine bir alanı ortaya çıkarmak için bir gerekçe midir?


10

C # için genel rehberlik, bir özelliği her zaman ortak bir alan üzerinde kullanmaktır. Bu mantıklıdır - bir alanı açığa çıkararak çok fazla uygulama ayrıntısı ortaya çıkarırsınız. Bir özellik ile, kodu tüketmekten gizlenmesi için bu ayrıntıyı kapsüllersiniz ve uygulama değişiklikleri arayüz değişikliklerinden ayrılır.

Ancak, bazen bu kuralla ilgili olarak geçerli bir istisna olup olmadığını merak ediyorum readonly anahtar kelimeyle . Bu anahtar kelimeyi herkese açık bir alana uygulayarak, ekstra bir garanti vermiş olursunuz: değişmezlik. Bu sadece bir uygulama detayı değildir, değişmezlik bir tüketicinin ilgi duyabileceği bir şeydir. Bir readonlyalanın kullanılması onu kamu sözleşmesinin bir parçası haline getirir ve ayrıca ortak arayüzde değişiklik yapmak zorunda kalmadan gelecekteki değişiklikler veya miras tarafından kırılamayan bir şeydir. Bu bir mülkün sunamayacağı bir şey.

Bu nedenle, değişmezliği garanti etmek, readonly , bazı durumlarda bir mülk üzerinde bir alan midir?

(Açıklığa kavuşturmak için, kesinlikle bu seçimi her zaman yapmanız gerektiğini söylemiyorum, çünkü alan şu anda değişmez olur, sadece sınıfın tasarımının bir parçası olarak mantıklı olduğunda ve sözleşmesindeki değişmezliği dahil etmek için kullanılması amaçlanır. Çoğunlukla, üyenin bir üzerinde olması gerektiğinde interfaceveya tembel yükleme yapmak istediğinizde olduğu gibi, belirli durumlarda değil, bunun haklı olup olmayacağına odaklanan cevaplarla ilgileniyorum .)



1
@gnat Sadece açıklığa kavuşturmak için, "ReadOnly Property" ile VB.NET terminolojisini kullanıyorlar, bu da salt okunur bir alan değil , ayarlayıcı olmayan bir özellik anlamına geliyor . Sorumun amacı için, bu sorunun karşılaştırdığı iki seçenek eşdeğerdir - her ikisi de özellikleri kullanmaktadır.
Ben Aaronson

Yanıtlar:


6

Halka açık statik salt okunur alanlar kesinlikle iyidir. Adlandırılmış, sabit bir nesne istediğinizde olduğu gibi belirli durumlar için önerilirler, ancakconst anahtar kelimeyi .

Salt okunur üye alanları biraz daha karmaşıktır. Kamusal ayarlayıcı olmayan bir mülk üzerinde çok fazla avantaj elde edilmez ve büyük bir dezavantaj vardır: alanlar arayüzlerin üyesi olamaz. Bu nedenle, somut bir tür yerine bir arabirime karşı çalışmak üzere kodunuzu yeniden düzenlemeye karar verirseniz, salt okunur alanlarınızı halka açık mülk sahibi mülklerle değiştirmeniz gerekir.

Korunmuş ayarlayıcı içermeyen ortak sanal olmayan bir özellik, devralınan sınıfların destek alanına erişimleri yoksa, mirasa karşı koruma sağlar. Bu sözleşmeyi temel sınıfta tamamen uygulayabilirsiniz.

Sınıfın kamusal arayüzünü değiştirmeden üyenin "değişmezliğini" değiştirememek bu durumda bir engel teşkil etmez. Genel bir alanı bir mülke dönüştürmek istiyorsanız, uğraşmanız gereken iki durum olması dışında sorunsuz bir şekilde ilerler:

  1. Bu nesnenin bir üyesine yazan herhangi bir şey, örneğin: object.Location.X = 4yalnızca Locationbir alan varsa mümkündür . Yine de bu salt okunur bir yapıyı değiştiremeyeceğiniz için salt okunur bir alanla ilgili değildir. (Bu, Locationbir değer türü olduğunu varsayarsa , bu sorun yine de geçerli olmaz çünküreadonly bu tür şeylere karşı koruma sağlamaz.)
  2. Değeri outveya olarak ileten bir yönteme yapılan her çağrı ref. Yine, bunun nedeni, bir salt okunur bir alan için gerçekten alakalı değildir outve refparametreler modifiye olsun eğilimindedir ve bu out veya ref olarak bir salt okunur değerini geçmesine zaten derleyici hatası var.

Başka bir deyişle, salt okunur bir alanı salt okunur bir özelliğe dönüştürmek ikili uyumluluğu bozsa da, diğer kaynak kodunun yalnızca bu değişikliği gerçekleştirmek için herhangi bir değişiklik yapılmadan yeniden derlenmesi gerekir. Bu garantinin kırılmasını gerçekten kolaylaştırır.

readonlyÜye alanına herhangi bir avantaj görmüyorum ve bir arayüzde bu tür şeylere sahip olamamak benim için kullanamayacağım bir dezavantaj.


İlgi içinde, neden olan kamu statik salt okunur tamam Fields? Sadece örnekleme yöntemlerini dışlamak, değiştirilemeyen alanlardaki (isabet sayma, tembel yükleme, vb.) Özellikler için kullanım örneklerinin çoğunu kaldırması mıdır?
Ben Aaronson

Herkese açık bir salt okunur alanın salt okunur özelliğe karşı ana dezavantajı ortadan kalkmıştır - statik üyeler arayüzlerin bir parçası olamaz, bu yüzden benzer temeldedir. Salt okunur bir statik özelliğin başlatılması gereken depolama alanına ihtiyacı vardır ya da her çağrıldığında dönüş değerini yeniden oluşturması gerekirken, salt okunur bir alan daha basit bir sözdizimine sahip olacak ve statik kurucu tarafından başlatılacaktır. Bence genel bir statik salt okunur alan, normalde bir alanı açığa çıkarmak için dezavantajların hiçbiri ile JIT tarafından daha fazla optimizasyon potansiyeli olduğunu düşünüyorum.
Erik

2

Deneyimlerime göre, readonlyanahtar kelime vaat ettiği sihir değil.

Örneğin, kurucunun basit olduğu bir sınıfınız var. Kullanımı (ve inşaattan sonra sınıf özelliklerinin / alanlarının bazılarının değişmez olması) önemli olmadığını düşünebilirsiniz, bu nedenlereadonly anahtar kelimeyi .

Daha sonra sınıf daha karmaşık hale gelir ve kurucu da öyle olur. (Diyelim ki bu, deneysel veya kapsam / kontrol dışında yakınlaştırma hızı yeterince yüksek olan bir projede gerçekleşiyor, ancak bir şekilde çalışmasını sağlamanız gerekiyor.)readonly Yalnızca yapıcı içinde değiştirilebilecek - bu yöntem yalnızca bir kurucudan çağrılsa bile yöntemlerde değiştirilemez.

Bu teknik sınırlama C # tasarımcıları tarafından kabul edilmiştir ve gelecekteki bir sürümde düzeltilebilir. Ama düzeltilinceye kadarreadonly daha kısıtlayıcıdır ve bazı kötü kodlama stillerini teşvik edebilir (her şeyi yapıcı yöntemine koyarak).

Hatırlatma olarak, ne readonlykamuya açık olan ne de mülk sahibi olmayan bir özellik "tamamen başlatılmış bir nesne" için herhangi bir garanti vermez . Başka bir deyişle, "tam olarak başlatılmış" ın ne anlama geldiğine ve onu istem dışı kullanıma karşı nasıl koruyacağına karar veren bir sınıfın tasarımcısıdır ve bu koruma genellikle kusursuz değildir, yani birisinin etrafında bir yol bulabileceği anlamına gelir.


1
Basit kurucular tutmayı tercih - bkz brendan.enrick.com/post/... , blog.ploeh.dk/2011/03/03/InjectionConstructorsshouldbesimple böylece aslında, salt okunur teşvik iyi kodlama stili
AlexFoxGill

1
Bir kurucu, bir readonlyalanı outveya refparametresi olarak diğer yöntemlere geçirebilir ; bu daha sonra uygun gördüklerinde onu değiştirmekte serbesttir.
supercat

1

Alanlar DAİMA uygulama detaylarıdır. Uygulama ayrıntılarınızı göstermek istemezsiniz.

Yazılım mühendisliğinin temel ilkeleri, gelecekte gereksinimlerin ne olacağını bilmememizdir. Alanınız readonlybugün iyi olsa da, yarının gereksinimlerinin bir parçası olacağını öne sürecek hiçbir şey yok. Yarın bu alana kaç kez erişildiğini belirlemek için bir isabet sayacı uygulamaya ihtiyaç varsa ne olur? Alt sınıfların alanı geçersiz kılmasına izin vermeniz gerekiyorsa ne olur?

Özellikleri kullanmak çok kolay ve ortak alanlardan çok daha esnektir, hem dilimi olarak c # seçeceğim hem de sınıfta genel salt okunur alanları kullanacağım tek bir kullanım durumu düşünemiyorum. Performans o kadar sıkı olsaydı, ekstra yöntem çağrısının isabetini alamazdım, muhtemelen farklı bir dil kullanıyordum.

Biz sırf olabilir dil ile bir şey yapmak biz anlamına gelmez should dille bir şeyler yapın.

Aslında dil tasarımcılarının alanların halka açılmasına izin verdiğinden pişmanlık duyup duymadığını merak ediyorum. Hatta kodumda const olmayan genel alanları kullanmayı düşündüğüm son zamanı hatırlayamıyorum.


1
Gelecekteki esneklikte inşa etmenin önemini anlıyorum, ancak tabii ki, örneğin, Rationalhalka açık, değişmez Numeratorve Denominatorüyeler gibi bir sınıf yazıyorsam , bu üyelerin tembel yükleme veya isabet sayacı veya benzer?
Ben Aaronson

Ancak, floattürlerini kullanan Numeratorve Denominatordeğiştirilmesinin gerekmeyeceğinden emin olabilir misiniz doubles?
Stephen

1
Ee, hayýr, kesinlikle ne floatde olmamalýlar double. Olmalılar int, longya da BigInteger. Belki bunların değişmesi gerekir ... ama eğer öyleyse ortak arayüzde de değişmeleri gerekir, bu yüzden gerçekten özellikleri kullanmak bu detayın etrafında kapsülleme yapmaz.
Ben Aaronson

-3

Hayır. Bu bir gerekçe değil.

Salt okunurluğu bir gerekçe olarak değişmezliğin garantisi olarak kullanmak daha çok bir hack gibidir.

Salt okunur, değişken tanımlandığında o yapıcı o tarafından atanan değer anlamına gelir.

Bence kötü bir uygulama olacak

Değişmezliği gerçekten garanti etmek istiyorsanız, bir arayüz kullanın, eksilerinden daha artıları vardır.

Basit arayüz örneği: resim açıklamasını buraya girin


1
"arayüz kullan" Nasıl?
Ben Aaronson
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.