C # 'da, bir alanı bir özellikten farklı kılan nedir ve ne zaman bir özellik yerine alan kullanılmalıdır?
C # 'da, bir alanı bir özellikten farklı kılan nedir ve ne zaman bir özellik yerine alan kullanılmalıdır?
Yanıtlar:
Özellikler alanları açığa çıkarır. Alanlar (neredeyse her zaman) bir sınıfa özel tutulmalı ve get ve set özellikleri yoluyla erişilmelidir. Özellikler, sınıfınızı kullanan şeylerin eriştiği dış yolu etkilemeden alanları değiştirmenize izin veren bir soyutlama düzeyi sağlar.
public class MyClass
{
// this is a field. It is private to your class and stores the actual data.
private string _myField;
// this is a property. When accessed it uses the underlying field,
// but only exposes the contract, which will not be affected by the underlying field
public string MyProperty
{
get
{
return _myField;
}
set
{
_myField = value;
}
}
// This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
// used to generate a private field for you
public int AnotherProperty{get;set;}
}
@Kent, Özelliklerin alanları kapsüllemek için gerekli olmadığını, diğer alanlarda bir hesaplama yapabileceğini veya başka amaçlara hizmet edebileceğini belirtir.
@GSS, bir özelliğe erişildiğinde başka bir yararlı özellik olan doğrulama gibi başka mantık da yapabileceğinizi belirtir.
string
, sözleşmem: ~ 2bil uzunluğa kadar karakter atamak. Bir özellik ise DateTime
, benim sözleşmem: DateTime sınırları dahilinde, arayabileceğim herhangi bir sayı atayın. Yaratan ayarlayıcılara kısıtlamalar eklerse, bu kısıtlamalar iletilmez. Ancak, bunun yerine, içerik oluşturucu türü olarak string
değiştirirse Surname
, yeni Soyadı sınıfı kısıtlamaları bildirir ve özelliğin public Surname LastName
ayarlayıcı doğrulaması yoktur. Ayrıca, Surname
yeniden kullanılabilir.
Surname
benim örneğimde, yeniden kullanılabilir olduğundan, daha sonra bir özellik ayarlayıcıdaki bu doğrulamaları koddaki diğer yerlere kopyalamak / yapıştırmak konusunda endişelenmenize gerek yoktur. Soyadı için iş kurallarında herhangi bir değişiklik yaparsanız, bir Soyadı doğrulamasının birden fazla yerde olup olmadığını merak etmeyin. Value Objects
Nesneye yönelik programlama ilkeleri, bir sınıfın iç işleyişinin dış dünyadan gizlenmesi gerektiğini söyler. Bir alanı ortaya çıkarırsanız, özünde sınıfın dahili uygulamasını ortaya koyarsınız. Bu nedenle, bize bağlı olarak kodu bozmadan uygulamayı değiştirebilmemizi sağlamak için alanları Özellikler (veya Java durumundaki yöntemler) ile sarıyoruz. Mülke mantık koyabildiğimizi görmek, ihtiyaç duymamız halinde doğrulama mantığı vb. Gerçekleştirmemizi de sağlar. C # 3, muhtemelen kafa karıştırıcı otoproditite kavramına sahiptir. Bu özelliği basitçe tanımlamamıza izin verir ve C # 3 derleyicisi bizim için özel alanı oluşturur.
public class Person
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public int Age{get;set;} //AutoProperty generates private field for us
}
public int myVar { get; set; }
gerçekten açılımı (ve bunu nedeni olduğunu tahmin bu sorunun isabetlerinin en az% 50'si için).
virtual
kendisi nesne yönelimli programlamanın bir parçasıdır.
virtual
olsa kendi başına OOP çağırmak olmaz . OOP'u etkinleştiren anahtar araçlardan biri olan polimorfizmi mümkün kılan bir araçtır. Bu kendi başına OOP değil ve kamusal bir otoprodüksiyon hakkında doğası gereği hiçbir şey yoktur. Ya yansıma ya da OOP ile ilgili veri bağlama gibi şeyleri saymazdım. Normalde bu konuda bilgiç olmazdım, ancak cevap OO ilkelerini kod örneğinin arkasındaki itici güç olarak özellikle belirtti ve buna katılmıyorum.
Önemli bir fark, arayüzlerin özelliklere sahip olabileceği, ancak alanlara sahip olamayacağıdır. Bu, bana göre, özelliklerin bir sınıfın genel arabirimini tanımlamak için kullanılması gerektiğinin altını çizerken, alanlar bir sınıfın özel, iç çalışmalarında kullanılmalıdır. Kural olarak nadiren kamusal alanlar yaratırım ve benzer şekilde nadiren kamusal olmayan mülkler yaratırım.
Viteslerin dönmesini sağlayabilecek özellikleri kullanma konusunda birkaç örnek vereceğim:
Özellikler'i kullanarak, özelliğin değeri değiştirildiğinde (aka. PropertyChangedEvent) veya değer iptali desteklemek için değer değiştirilmeden önce bir olayı yükseltebilirsiniz.
(Doğrudan erişim) alanlarıyla bu mümkün değildir.
public class Person {
private string _name;
public event EventHandler NameChanging;
public event EventHandler NameChanged;
public string Name{
get
{
return _name;
}
set
{
OnNameChanging();
_name = value;
OnNameChanged();
}
}
private void OnNameChanging(){
NameChanging?.Invoke(this,EventArgs.Empty);
}
private void OnNameChanged(){
NameChanged?.Invoke(this,EventArgs.Empty);
}
}
Birçoğu teknik artıları ve eksileri ile açıkladık yana Properties
ve Field
, 's zaman gerçek zamanlı örneklere içine almak için.
1. Özellikler, salt okunur erişim düzeyini ayarlamanızı sağlar
Durumunu düşünün dataTable.Rows.Count
ve dataTable.Columns[i].Caption
. Sınıftan geliyorlar DataTable
ve her ikisi de bize açık. Onlara erişim seviyesindeki fark, değeri ayarlayamadığımız, dataTable.Rows.Count
ancak okuyabildiğimiz ve yazabildiğimizdir dataTable.Columns[i].Caption
. Bu mümkün mü Field
? Hayır!!! Bu ile yapılabilirProperties
.
public class DataTable
{
public class Rows
{
private string _count;
// This Count will be accessable to us but have used only "get" ie, readonly
public int Count
{
get
{
return _count;
}
}
}
public class Columns
{
private string _caption;
// Used both "get" and "set" ie, readable and writable
public string Caption
{
get
{
return _caption;
}
set
{
_caption = value;
}
}
}
}
2. PropertyGrid'deki Özellikler
Button
Visual Studio'da çalışmış olabilirsiniz . Onun özellikleri gösterilmiştir PropertyGrid
gibi Text
, Name
biz sürükleyip bir düğme damla ve biz özelliklerini tıkladığınızda, otomatik olarak sınıf bulacaksınız zaman vb Button
ve filtreler Properties
bu ve gösteri PropertyGrid
( PropertyGrid
gösterilmezField
kamu olsa bile).
public class Button
{
private string _text;
private string _name;
private string _someProperty;
public string Text
{
get
{
return _text;
}
set
{
_text = value;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
[Browsable(false)]
public string SomeProperty
{
get
{
return _someProperty;
}
set
{
_someProperty= value;
}
}
İçinde PropertyGrid
, özellikleri Name
ve Text
gösterilecek, ancak gösterilmeyecek SomeProperty
. Neden??? Özellikler kabul edebilir Çünkü Öznitelikler'i . [Browsable(false)]
Yanlış olduğu durumlarda gösterilmez .
3. Özellikler içindeki ifadeleri yürütebilir
public class Rows
{
private string _count;
public int Count
{
get
{
return CalculateNoOfRows();
}
}
public int CalculateNoOfRows()
{
// Calculation here and finally set the value to _count
return _count;
}
}
4. Ciltleme Kaynağında sadece Özellikler kullanılabilir
Bağlama Kaynağı , kod satırlarının sayısını azaltmamıza yardımcı olur. Fields
tarafından kabul edilmediBindingSource
. Bunun Properties
için kullanmalıyız .
5. Hata ayıklama modu
Field
Bir değeri tutmak için kullandığımızı düşünün . Bir noktada hata ayıklamak ve değerin bu alan için nerede boş kaldığını kontrol etmemiz gerekir. Kod satırı sayısının 1000'den fazla olduğu yerde yapmak zor olacaktır. Bu gibi durumlarda Property
hata ayıklama modunu kullanabilir ve içinde hata ayıklama modunu ayarlayabiliriz Property
.
public string Name
{
// Can set debug mode inside get or set
get
{
return _name;
}
set
{
_name = value;
}
}
Bir alan bir sınıf veya yapı doğrudan bildirilmiş bir değişkendir. Bir sınıf veya yapı örnek alanları, statik alanları veya her ikisini birden içerebilir. Genellikle, alanları yalnızca özel veya korumalı erişilebilirliğe sahip değişkenler için kullanmalısınız . Sınıfınızın istemci koduna gösterdiği veriler, yöntemler, özellikler ve dizinleyiciler aracılığıyla sağlanmalıdır . Dahili yapılara dolaylı erişim için bu yapıları kullanarak, geçersiz giriş değerlerine karşı koruma sağlayabilirsiniz.
Bir özellik , okuma yazma, ya da özel bir alanın değerini hesaplamak için esnek bir mekanizma sağlayan bir üyesidir. Özellikler, herkese açık veri üyeleriymiş gibi kullanılabilir, ancak aslında erişimci adı verilen özel yöntemlerdir . Bu, verilere kolayca erişilmesini sağlar ve yine de yöntemlerin güvenliğini ve esnekliğini artırmaya yardımcı olur . Özellikler, bir sınıfın uygulama veya doğrulama kodunu gizlerken genel bir değer alma ve ayarlama yöntemini göstermesini sağlar. Özellik değerini döndürmek için bir get özellik erişimcisi kullanılır ve yeni bir değer atamak için set erişimcisi kullanılır.
Mülklerin birincil avantajı, bir nesne üzerindeki verilere genel arabirimini bozmadan erişme şeklini değiştirmenize izin vermesidir. Örneğin, fazladan doğrulama eklemeniz veya depolanmış bir alanı hesaplanmış olarak değiştirmeniz gerekiyorsa, alanı başlangıçta bir özellik olarak gösterdiyseniz bunu kolayca yapabilirsiniz. Bir alanı doğrudan doğrudan açıkladıysanız, yeni işlevselliği eklemek için sınıfınızın genel arayüzünü değiştirmeniz gerekir. Bu değişiklik, mevcut istemcileri bozar ve kodunuzun yeni sürümünü kullanmadan önce yeniden derlenmelerini gerektirir.
Geniş tüketim için tasarlanmış bir sınıf kütüphanesi yazarsanız (milyonlarca kişi tarafından kullanılan .NET Framework gibi), bu bir sorun olabilir. Bununla birlikte, küçük bir kod tabanı içinde dahili olarak kullanılan bir sınıf yazıyorsanız (örneğin <= 50 K satır), bu gerçekten önemli değil, çünkü hiç kimse değişikliklerinizden olumsuz etkilenmeyecektir. Bu durumda, bu sadece kişisel tercihe bağlıdır.
Özellikler asimetrik erişimi destekler, yani bir alıcı ve ayarlayıcıya veya ikisinden sadece birine sahip olabilirsiniz. Benzer şekilde özellikler alıcı / ayarlayıcı için bireysel erişilebilirliği destekler. Alanlar her zaman simetriktir, yani her zaman değeri alabilir ve ayarlayabilirsiniz. Bunun istisnası, başlatma işleminden sonra açık bir şekilde ayarlanamayan salt okunur alanlardır.
Özellikler çok uzun süre çalışabilir, yan etkileri olabilir ve hatta istisnalar atabilir. Alanlar hızlıdır, yan etkisi yoktur ve hiçbir zaman istisna oluşturmaz. Yan etkiler nedeniyle, bir özellik her çağrı için farklı bir değer döndürebilir (DateTime.Now, örneğin DateTime.Now için her zaman DateTime.Now'a eşit değildir). Alanlar her zaman aynı değeri döndürür.
Alanlar out / ref parametreleri için kullanılabilir, özellikler kullanılamaz. Özellikler ek mantığı destekler - bu, diğer şeylerin yanı sıra tembel yüklemeyi uygulamak için kullanılabilir.
Özellikler, değeri elde etmek / ayarlamak için ne anlama geliyorsa onu içine alarak bir soyutlama seviyesini destekler.
Çoğu durumda / tüm özellikleri kullanın, ancak yan etkilerden kaçınmaya çalışın.
Arka planda bir özellik yöntemlere derlenir. Böylece bir Name
özellik get_Name()
ve içine derlenir set_Name(string value)
. Derlenmiş kodu incelerseniz bunu görebilirsiniz. Bu nedenle, bunları kullanırken (çok) küçük bir performans yükü vardır. Normalde, bir alanı dışarıya maruz bırakırsanız her zaman bir Özellik kullanırsınız ve değerin doğrulanması gerekiyorsa genellikle dahili olarak kullanırsınız.
Özel değişkeninizin (alanınızın) sınıfınızın nesnesine diğer sınıflardan erişmesini istediğinizde, bu değişkenler için özellikler oluşturmanız gerekir.
örneğin, "id" ve "name" olarak adlandırılan değişkenlerim varsa, ancak bu değişkenin sınıf dışında okuma / yazma işlemi için gerekli olduğu durumlar olabilir. Bu durumda, özellik, özellik için tanımlanan get / set'e bağlı olarak bu değişkeni okuma / yazma için bana yardımcı olabilir. Bir özellik, salt okunur / yazılı olarak / salt okunur olabilir.
işte demo
class Employee
{
// Private Fields for Employee
private int id;
private string name;
//Property for id variable/field
public int EmployeeId
{
get
{
return id;
}
set
{
id = value;
}
}
//Property for name variable/field
public string EmployeeName
{
get
{
return name;
}
set
{
name = value;
}
}
}
class MyMain
{
public static void Main(string [] args)
{
Employee aEmployee = new Employee();
aEmployee.EmployeeId = 101;
aEmployee.EmployeeName = "Sundaran S";
}
}
Buradaki ikinci soru, "bir mülk yerine bir alan ne zaman kullanılmalıdır?", Bu diğer cevapta sadece kısaca değinilmektedir ve bu da buna çok fazla detay vermemektedir.
Genel olarak, diğer tüm cevaplar iyi tasarımla ilgilidir: alanları açığa çıkarmak için özellikleri göstermeyi tercih edin. Muhtemelen etmeyecek olsa düzenli kendinizi söyleyerek bulmak bu, "vay, yerine bir özelliğin bu dalı haline olsaydı olurdu ne kadar kötü şeyler hayal" o kadar , sen vay" derdi bir durum düşünmek daha nadir Tanrıya şükür burada mülk yerine tarla kullandım. "
Ancak alanların özelliklerin üzerinde olması bir avantajdır ve bu onların "ref" / "out" parametreleri olarak kullanılabilmesidir. Aşağıdaki imzayla bir yönteminiz olduğunu varsayalım:
public void TransformPoint(ref double x, ref double y);
ve bunun gibi bir diziyi dönüştürmek için bu yöntemi kullanmak istediğinizi varsayalım:
System.Windows.Point[] points = new Point[1000000];
Initialize(points);
İşte X ve Y özellikleri olduğu için bunu yapmanın en hızlı yolunu düşünüyorum :
for (int i = 0; i < points.Length; i++)
{
double x = points[i].X;
double y = points[i].Y;
TransformPoint(ref x, ref y);
points[i].X = x;
points[i].Y = y;
}
Ve bu oldukça iyi olacak! Aksi kanıtlanan ölçümleriniz olmadığı sürece, kıyameti atmak için bir neden yoktur. Ama teknik olarak bu kadar hızlı olması garanti edilmediğine inanıyorum:
internal struct MyPoint
{
internal double X;
internal double Y;
}
// ...
MyPoint[] points = new MyPoint[1000000];
Initialize(points);
// ...
for (int i = 0; i < points.Length; i++)
{
TransformPoint(ref points[i].X, ref points[i].Y);
}
Bazı ölçümleri kendim yapıyorum, alanlı sürüm, özellikli sürüm olarak yaklaşık% 61 zaman alır (.NET 4.6, Windows 7, x64, yayın modu, hata ayıklayıcı bağlı değil). Yöntem ne kadar pahalı olursa TransformPoint
, farkın o kadar az belirgin olduğu görülür. Bunu kendiniz tekrarlamak için, ilk satırın yorumlanmış ve yorumlanmamış olarak çalıştırın.
Yukarıdakiler için herhangi bir performans avantajı olmasa bile, Kilitli veya Uçucu yöntemler ailesini çağırırken olduğu gibi ref ve out parametrelerini kullanmanın yararlı olabileceği başka yerler de vardır . Not: Bunun sizin için yeni olması durumunda, Uçucu temel olarak volatile
anahtar kelime tarafından sağlanan davranışı elde etmenin bir yoludur . Gibi volatile
, adından da anlaşılacağı gibi tüm iplik güvenliği sıkıntılarını sihirli bir şekilde çözmez.
Kesinlikle "ah, özellikler yerine alanları açığa çıkarmaya başlamalısın" diye savunduğumu düşünmek istemiyorum. Mesele şu ki, bu üyeleri düzenli olarak "ref" veya "out" parametreleri alan çağrılarda kullanmanız gerekiyorsa, özellikle özelliklerin katma değer unsurlarından herhangi birine ihtiyaç duyması muhtemel olmayan basit bir değer türü olabilecek bir şeyde, bir tartışma yapılabilir.
Alanlar ve özellikler birbirine benzemekle birlikte, bunlar tamamen farklı 2 dil öğesidir.
Alanlar, verilerin sınıf düzeyinde depolanmasının tek mekanizmasıdır. Alanlar kavramsal olarak sınıf kapsamındaki değişkenlerdir. Bazı verileri sınıflarınızın (nesnelerin) örneklerine depolamak istiyorsanız alanları kullanmanız gerekir. Başka seçenek yok. Özellikler herhangi bir veriyi depolayamasa da, bunu yapabildikleri görülebilir. Bkz. Aşağıdaki.
Öte yandan özellikler asla veri depolamaz. Bunlar, alanlarla benzer şekilde sözdizimsel olarak çağrılabilen ve çoğu durumda bazı karışıklıkların kaynağı olan alanlara (okuma veya yazma için) erişen yöntem çiftleridir (al ve ayarla). Ancak özellik yöntemleri (sabit prototip gibi bazı sınırlamalarla) düzenli C # yöntemleri olduğundan, normal yöntemler ne yapabilirlerse yapabilirler. Bu, 1000 satır kod alabilecekleri, istisnalar atabilecekleri, başka yöntemler çağırabilecekleri, hatta sanal, soyut veya geçersiz kılınabilecekleri anlamına gelir. Özellikleri özel kılan şey, C # derleyicisinin bazı ekstra meta verileri, belirli özellikleri (yaygın olarak kullanılan özellik) aramak için kullanılabilen derlemeler halinde depolamasıdır.
Get ve set özelliği yöntemleri aşağıdaki prototiplere sahiptir.
PROPERTY_TYPE get();
void set(PROPERTY_TYPE value);
Bu, özelliklerin bir alan ve 2 karşılık gelen yöntem tanımlanarak 'benzetilebileceği' anlamına gelir.
class PropertyEmulation
{
private string MSomeValue;
public string GetSomeValue()
{
return(MSomeValue);
}
public void SetSomeValue(string value)
{
MSomeValue=value;
}
}
Bu tür özellik öykünmesi, standart C ++ gibi özellikleri desteklemeyen programlama dilleri için tipiktir. C # 'da her zaman özellikleri alanlarınıza nasıl erişeceğinize tercih etmelisiniz.
Yalnızca alanlar bir veri depolayabildiğinden, daha fazla alan sınıfı içerdiğinden, bu sınıfın daha fazla bellek nesnesi tüketilir. Öte yandan, bir sınıfa yeni özellikler eklemek, bu sınıftaki nesneleri büyütmez. İşte örnek.
class OneHundredFields
{
public int Field1;
public int Field2;
...
public int Field100;
}
OneHundredFields Instance=new OneHundredFields() // Variable 'Instance' consumes 100*sizeof(int) bytes of memory.
class OneHundredProperties
{
public int Property1
{
get
{
return(1000);
}
set
{
// Empty.
}
}
public int Property2
{
get
{
return(1000);
}
set
{
// Empty.
}
}
...
public int Property100
{
get
{
return(1000);
}
set
{
// Empty.
}
}
}
OneHundredProperties Instance=new OneHundredProperties() // !!!!! Variable 'Instance' consumes 0 bytes of memory. (In fact a some bytes are consumed becasue every object contais some auxiliarity data, but size doesn't depend on number of properties).
Özellik yöntemleri her şeyi yapabilmesine rağmen, çoğu durumda nesnelerin alanlarına erişmenin bir yolu olarak hizmet ederler. Bir alanı diğer sınıflar için erişilebilir yapmak istiyorsanız, 2 yolla yapabilirsiniz.
İşte ortak alanları kullanan bir sınıf.
class Name
{
public string FullName;
public int YearOfBirth;
public int Age;
}
Name name=new Name();
name.FullName="Tim Anderson";
name.YearOfBirth=1979;
name.Age=40;
Kod tamamen geçerli olsa da, tasarım açısından birçok dezavantajı vardır. Alanlar hem okunabilir hem de yazılabilir olduğundan, kullanıcının alanlara yazmasını engelleyemezsiniz. readonly
Anahtar kelime uygulayabilirsiniz , ancak bu şekilde salt okunur alanları yalnızca yapıcıda başlatmanız gerekir. Dahası, hiçbir şey alanlarınızda geçersiz değerler depolamanızı engellemez.
name.FullName=null;
name.YearOfBirth=2200;
name.Age=-140;
Kod geçerlidir, tüm ödevler mantıksız olsa da yürütülecektir. Age
negatif bir değere sahiptir, YearOfBirth
gelecekte çok uzaktır ve Yaşa karşılık gelmez ve FullName
boştur. Alanlarla kullanıcıların class Name
bu tür hatalar yapmasını engelleyemezsiniz .
İşte bu sorunları gideren özelliklere sahip bir kod.
class Name
{
private string MFullName="";
private int MYearOfBirth;
public string FullName
{
get
{
return(MFullName);
}
set
{
if (value==null)
{
throw(new InvalidOperationException("Error !"));
}
MFullName=value;
}
}
public int YearOfBirth
{
get
{
return(MYearOfBirth);
}
set
{
if (MYearOfBirth<1900 || MYearOfBirth>DateTime.Now.Year)
{
throw(new InvalidOperationException("Error !"));
}
MYearOfBirth=value;
}
}
public int Age
{
get
{
return(DateTime.Now.Year-MYearOfBirth);
}
}
public string FullNameInUppercase
{
get
{
return(MFullName.ToUpper());
}
}
}
Sınıfın güncellenmiş sürümü aşağıdaki avantajlara sahiptir.
FullName
ve YearOfBirth
geçersiz değerler için kontrol edilir.Age
yazılamaz. Bu gelen callculated oluyor YearOfBirth
ve cari yıl.FullNameInUppercase
dönüştürür FullName
. Bu, özelliklerin alan değerleri kullanıcı için daha uygun biçimde sunmak için yaygın olarak kullanıldığı, örneğin DateTime
biçimin belirli sayısal sayısında geçerli yerel ayarı kullanan özellik kullanımının küçük bir örneğidir .Bunun yanında, özellikler normal .NET yöntemleri oldukları için sanal veya geçersiz kılınmış olarak tanımlanabilir. Normal yöntemlerde olduğu gibi aynı özellik yöntemleri için de aynı kurallar geçerlidir.
C #, özellik yöntemlerinde bir dizin parametresi olan özellikler olan dizinleyicileri de destekler. İşte örnek.
class MyList
{
private string[] MBuffer;
public MyList()
{
MBuffer=new string[100];
}
public string this[int Index]
{
get
{
return(MBuffer[Index]);
}
set
{
MBuffer[Index]=value;
}
}
}
MyList List=new MyList();
List[10]="ABC";
Console.WriteLine(List[10]);
C # 3.0, otomatik özellikleri tanımlamanıza izin verdiği için. İşte örnek.
class AutoProps
{
public int Value1
{
get;
set;
}
public int Value2
{
get;
set;
}
}
Her ne kadar class AutoProps
yalnızca özellikler içeriyor olsa da (veya benziyorsa), 2 değer saklayabilir ve bu sınıftaki nesnelerin boyutu sizeof(Value1)+sizeof(Value2)
= 4 + 4 = 8 bayta eşittir .
Bunun nedeni basit. Bir otomatik özellik tanımladığınızda, C # derleyicisi gizli alan içeren otomatik kod ve bu gizli alana erişen özellik yöntemlerine sahip bir özellik oluşturur. İşte derleyicinin ürettiği kod.
İşte derlenmiş derlemeden ILSpy tarafından üretilen bir kod . Sınıf, oluşturulan gizli alanları ve özellikleri içerir.
internal class AutoProps
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value1>k__BackingField;
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value2>k__BackingField;
public int Value1
{
[CompilerGenerated]
get
{
return <Value1>k__BackingField;
}
[CompilerGenerated]
set
{
<Value1>k__BackingField = value;
}
}
public int Value2
{
[CompilerGenerated]
get
{
return <Value2>k__BackingField;
}
[CompilerGenerated]
set
{
<Value2>k__BackingField = value;
}
}
}
Gördüğünüz gibi, derleyici değerleri depolamak için hala alanları kullanıyor - çünkü alanlar değerleri nesnelere depolamanın tek yolu.
Gördüğünüz gibi, özellikler ve alanlar benzer kullanım sözdizimine sahip olsalar da çok farklı kavramlardır. Otomatik özellikler veya olaylar kullansanız bile - gizli alanlar, gerçek verilerin depolandığı derleyici tarafından oluşturulur.
Bir alan değerini dış dünya için erişilebilir hale getirmeniz gerekiyorsa (sınıfınızın kullanıcıları) herkese açık veya korumalı alanları kullanmayın. Alanlar her zaman özel olarak işaretlenmelidir. Özellikler, değer denetimleri, biçimlendirme, dönüşümler vb. Yapmanızı ve genellikle kodunuzu daha sonraki değişiklikler için daha güvenli, daha okunabilir ve daha genişletilebilir hale getirmenize olanak tanır.
Eğer iplik ilkellerini kullanacaksanız, alanları kullanmak zorunda kalırsınız. Özellikler, dişli kodunuzu kırabilir. Bunun dışında cory'nin söyledikleri doğrudur.
(Bu gerçekten bir yorum olmalı, ancak yorum gönderemiyorum, bu yüzden bir yazı olarak uygun değilse lütfen bahane edin).
Bir keresinde, eşdeğer özellik def sadece bir alana erişiyordu gibi özellikleri yerine ortak alanları kullanmak olduğu bir yerde çalıştı:
get { return _afield; }
set { _afield = value; }
Gerekçeleri, kamu alanının gerektiğinde ileride bir mülke dönüştürülebilmesiydi. O zamanlar bana biraz garip geldi. Bu yazılara bakılırsa, burada pek fazla kişi aynı fikirde değil. Bir şeyi değiştirmeye çalışmak için ne söyleyebilirdin?
Düzenleme: Bu yerde tüm kod tabanı aynı anda derlenmiş olduğunu eklemeliyim, bu yüzden (ortak bir alanı bir özelliğe değiştirerek) sınıfların ortak arabirimi değiştirmenin bir sorun olmadığını düşünmüş olabilir.
Teknik olarak, bir fark olduğunu düşünmüyorum, çünkü özellikler sadece kullanıcı tarafından oluşturulan veya derleyici tarafından otomatik olarak oluşturulan alanların etrafındaki sarmalayıcılardır.Özelliklerin amacı kapsüllemeyi zorlamak ve hafif bir yöntem benzeri özellik sunmaktır. Alanları kamuya açıklamak sadece kötü bir uygulamadır, ancak herhangi bir sorunu yoktur.
Alanlar, sıradan üye değişkenler veya bir sınıfın üye örnekleridir. Özellikler, değerlerini almak ve ayarlamak için bir soyutlamadır . Sınıfta bir alanı özel olarak gösterdiğinizde bir alanı değiştirmenin ve almanın bir yolunu sunduğundan, özelliklere erişimci de denir. Genel olarak, üye değişkenlerinizi özel olarak bildirmeli, daha sonra bu değişkenlerin özelliklerini bildirmeli veya tanımlamalısınız.
class SomeClass
{
int numbera; //Field
//Property
public static int numbera { get; set;}
}
Özellikler alanları kaplar, böylece ayarlanacak veya alınacak değer üzerinde ek işlem gerçekleştirmenizi sağlar. Alan değeri üzerinde herhangi bir ön işlem veya son işlem yapmayacaksanız, özellikleri kullanmak aşırı derecede doludur.
IMO, Özellikler yalnızca daha önce kullandığımız "SetXXX ()" "GetXXX ()" işlevler / yöntemler / arayüz çiftleridir, ancak daha özlü ve zariftir.
Geleneksel olarak özel alanlar alıcı ve ayarlayıcı yöntemleriyle ayarlanır. Daha az kod uğruna alanları ayarlamak için özellikleri kullanabilirsiniz.
"Araba" olan bir sınıfınız olduğunda. Özellikleri renk, şekil ..
Alanlar, bir sınıf kapsamında tanımlanan değişkenlerdir.
Wikipedia'dan - Nesneye yönelik programlama :
Nesne yönelimli programlama (OOP) veri içeren veri yapıları olan ve genellikle nitelik olarak bilinen veri yapıları olan "nesneler" kavramına dayanan bir programlama paradigmasıdır ; ve genellikle yöntem olarak bilinen prosedürler biçiminde kodlama . (vurgu eklendi)
Özellikler aslında bir nesnenin davranışının bir parçasıdır, ancak nesnenin tüketicilerine nesnenin verileriyle çalışma yanılsaması / soyutlaması vermek için tasarlanmıştır.
Bir alan tasarımım, bir alanın sadece üst öğesi, dolayısıyla sınıf tarafından değiştirilmesi gerektiğidir. Sonuç değişken özel olur, daha sonra sadece Get ile mülkiyet sistemi üzerinden gitmek dışında sınıfları / yöntemleri okuma hakkını verebilmek için. Alan daha sonra özellik ve salt okunur tarafından alınır! Eğer değiştirmek istiyorsanız yöntemleri (örneğin kurucu) üzerinden gitmek zorunda ve ben güvenli hale getirmek için bu yolu sayesinde, biz "flanş" çünkü bizim kod üzerinde daha iyi kontrol var buluyorum. Biri her şeyi herkese açık bir şekilde koyabilir, bu yüzden her olası durum, değişkenler / yöntemler / sınıflar vb. Kavramı ... bence sadece kodun geliştirilmesi, sürdürülmesi için bir yardımcıdır. Örneğin, bir kişi ortak alanlarla bir koda devam ederse, her şeyi yapabilir ve bu nedenle "mantıksız" şeyler yapabilir. amaç ile ilgili olarak, kodun neden yazıldığının mantığı. Benim açımdan.
Klasik bir model özel alan / kamu salt okunur özellikleri kullandığımda, 10 erler için 10 kamu özellikleri yazmalısınız! Kod gerçekten daha hızlı olabilir. Özel ayarlayıcıyı keşfettim ve şimdi sadece özel bir ayarlayıcı ile ortak özellikleri kullanıyorum. Ayarlayıcı arka planda özel bir alan oluşturur.
Bu yüzden eski klasik programlama tarzım:
public class MyClass
{
private int _id;
public int ID { get { return _id; } }
public MyClass(int id)
{
_id = id;
}
}
Yeni programlama tarzım:
public class MyClass
{
public int ID { get; private set; }
public MyClass(int id)
{
ID = id;
}
}
Bir düşünün: Bu odaya girmek için bir odanız ve bir kapınız var. Kimin nasıl geldiğini kontrol etmek ve odanızı güvence altına almak istiyorsanız, özellikleri kullanmalısınız, aksi takdirde herhangi bir kapı olmayacaklar ve herkes herhangi bir düzenleme olmadan kolayca girebilir
class Room {
public string sectionOne;
public string sectionTwo;
}
Room r = new Room();
r.sectionOne = "enter";
İnsanlar bölüme giriyorBir çok kolay, kontrol yoktu
class Room
{
private string sectionOne;
private string sectionTwo;
public string SectionOne
{
get
{
return sectionOne;
}
set
{
sectionOne = Check(value);
}
}
}
Room r = new Room();
r.SectionOne = "enter";
Şimdi kişiyi kontrol ettin ve onunla kötü bir şey olup olmadığını biliyorsun
Alanlar, sınıflardaki değişkenlerdir. Alanlar, erişim değiştiricileri kullanarak kapsülleyebileceğiniz verilerdir.
Özellikler, bir nesneyle ilişkili durumları ve verileri tanımlamaları bakımından Alanlara benzer.
Bir alanın aksine, bir mülk, bir kişinin verileri nasıl okuduğunu ve yazdığını kontrol eden özel bir sözdizimine sahiptir, bunlar get ve set işleçleri olarak bilinir. Ayarlanan mantık genellikle doğrulama yapmak için kullanılabilir.
Özellikler özel tür bir sınıf üyesidir, Özelliklerde önceden tanımlanmış bir Set veya Get yöntemi kullanıyoruz.
Örneğin, Employee
ad, yaş ve Employee_Id için özel alanları olan bir sınıf alalım . Bu alanlara sınıfın dışından erişemeyiz, ancak bu özel alanlara özellikler aracılığıyla erişebiliriz.
Neden özellikleri kullanıyoruz?
Sınıf alanını herkese açık hale getirmek ve açıklamak risklidir, çünkü neyin atandığını ve geri döndüğünü kontrol edemezsiniz.
Bunu bir örnekle açıkça anlamak için kimlik, pasaport, isim olan bir öğrenci dersi alalım. Şimdi bu örnekte kamusal alanla ilgili bazı problemler
Bu sorunu gidermek için Get and set yöntemini kullanıyoruz.
// A simple example
public class student
{
public int ID;
public int passmark;
public string name;
}
public class Program
{
public static void Main(string[] args)
{
student s1 = new student();
s1.ID = -101; // here ID can't be -ve
s1.Name = null ; // here Name can't be null
}
}
Şimdi get ve set yöntemine bir örnek alalım
public class student
{
private int _ID;
private int _passmark;
private string_name ;
// for id property
public void SetID(int ID)
{
if(ID<=0)
{
throw new exception("student ID should be greater then 0");
}
this._ID = ID;
}
public int getID()
{
return_ID;
}
}
public class programme
{
public static void main()
{
student s1 = new student ();
s1.SetID(101);
}
// Like this we also can use for Name property
public void SetName(string Name)
{
if(string.IsNullOrEmpty(Name))
{
throw new exeception("name can not be null");
}
this._Name = Name;
}
public string GetName()
{
if( string.IsNullOrEmpty(This.Name))
{
return "No Name";
}
else
{
return this._name;
}
}
// Like this we also can use for Passmark property
public int Getpassmark()
{
return this._passmark;
}
}
Ek bilgi: Varsayılan olarak, alma ve ayarlama erişimcileri mülkün kendisi kadar erişilebilirdir. Üzerine daha kısıtlayıcı erişim değiştiricileri uygulayarak erişimcinin erişilebilirliğini tek tek (alma ve ayarlama için) kontrol edebilir / kısıtlayabilirsiniz.
Misal:
public string Name
{
get
{
return name;
}
protected set
{
name = value;
}
}
Burada get hâlâ herkese açıktır (mülk herkese açık olduğu için), ancak küme korumalıdır (daha kısıtlı bir erişim belirteci).
Özellikler alanı göstermek için kullanılır. Özel alanların değerlerinin okunabileceği, yazılabileceği veya manipüle edilebildiği erişimciler (set, get) kullanırlar.
Özellikler, depolama konumlarını adlandırmaz. Bunun yerine, değerlerini okuyan, yazan veya hesaplayan erişimcileri vardır.
Özellikleri kullanarak bir alanda ayarlanan veri türünde doğrulama ayarlayabiliriz.
Örneğin, yaş negatif olamayacağından, pozitif değerlere izin vermemiz gerektiğine dair özel tamsayı alan yaşımız vardır.
Bunu, alıcı ve ayarlayıcıları kullanarak ve mülk kullanarak iki şekilde yapabiliriz.
Using Getter and Setter
// field
private int _age;
// setter
public void set(int age){
if (age <=0)
throw new Exception();
this._age = age;
}
// getter
public int get (){
return this._age;
}
Now using property we can do the same thing. In the value is a key word
private int _age;
public int Age{
get{
return this._age;
}
set{
if (value <= 0)
throw new Exception()
}
}
Otomatik Uygulanan özellik, get ve set erişimcilerinde mantık oluşturmazsak, otomatik uygulanan özelliği kullanabiliriz.
U zaman otomatik uygulanan mülkiyet derler se özel, anonim alan oluşturur sadece get ve set erişimcilerine aracılığıyla erişilebilir.
public int Age{get;set;}
Soyut Özellikler Soyut bir sınıf, türetilmiş sınıfta uygulanması gereken soyut bir özelliğe sahip olabilir
public abstract class Person
{
public abstract string Name
{
get;
set;
}
public abstract int Age
{
get;
set;
}
}
// overriden something like this
// Declare a Name property of type string:
public override string Name
{
get
{
return name;
}
set
{
name = value;
}
}
Özel olarak bir özellik ayarlayabiliriz. Burada otomatik özelliği (sınıfta ayarlanmış olarak) özel olarak ayarlayabiliriz.
public int MyProperty
{
get; private set;
}
Bu kodla aynı şeyi elde edebilirsiniz. Bu özellik ayarında, değeri doğrudan alana ayarlamamız gerektiğinden kullanılamaz.
private int myProperty;
public int MyProperty
{
get { return myProperty; }
}
Vakaların büyük çoğunluğu, değişken bir ismin ( alanın ) aksine eriştiğiniz bir mülk adı olacaktır. Bunun nedeni, bir sınıftaki her veri parçasını korumak için .NET ve C # 'da iyi bir uygulama olarak kabul edilmesidir. , bir örnek değişken mi yoksa statik bir değişken mi (sınıf değişkeni) olsun, çünkü bir sınıfla ilişkilendirilir.
Tanımlamak, izin tekabül özelliklere sahip bu değişkenlerin tümünü koruyun seti ve elde erişimcileri ve veri parçalarını manipüle ederken doğrulama gibi şeyler.
Ancak Math sınıfı (Sistem ad alanı) gibi diğer durumlarda, sınıfa yerleştirilmiş birkaç statik özellik vardır. bunlardan biri matematik sabiti PI
Örneğin. Math.PI
ve PI iyi tanımlanmış bir veri parçası olduğundan, PI'nın birden fazla kopyasına ihtiyacımız yoktur, her zaman aynı değer olacaktır. Bu nedenle, statik değişkenler bazen verileri bir sınıfın nesnesi arasında paylaşmak için kullanılır, ancak bunlar genellikle bir veri parçasının yalnızca bir kopyasına ihtiyacınız olan sabit bilgiler için de kullanılır.