Properties
Özellikler C# dilinde birinci sınıf vatandaşlardır. Dil, geliştiricilerin tasarım amaçlarını doğru şekilde ifade eden kod yazmasına olanak tanıyan söz dizimini tanımlar.
Özelliklere erişildiğinde alanlar gibi davranır. Ancak, alanlardan farklı olarak, özellikler bir özelliğe erişildiğinde veya atandığında yürütülen deyimleri tanımlayan erişimcilerle birlikte uygulanır.
Özellik söz dizimi
Özelliklerin söz dizimi, alanlara yönelik doğal bir uzantıdır. Bir alan bir depolama konumu tanımlar:
public class Person
{
public string? FirstName;
// Omitted for brevity.
}
Özellik tanımı, bir get
ve set
erişimcisi için bu özelliğin değerini alan ve atayan bildirimler içerir:
public class Person
{
public string? FirstName { get; set; }
// Omitted for brevity.
}
Yukarıda gösterilen söz dizimi otomatik özellik söz dizimidir. Derleyici, özelliği yedekleyen alan için depolama konumunu oluşturur. Derleyici ayrıca ve set
erişimcilerinin gövdesini get
de uygular.
Bazen, bir özelliği türü için varsayılan değer dışında bir değere başlatmanız gerekir. C# özelliği için kapanış ayracından sonra bir değer ayarlayarak bunu etkinleştirir. özelliği için ilk değerin FirstName
yerine null
boş dize olmasını tercih edebilirsiniz. Aşağıda gösterildiği gibi bunu belirtebilirsiniz:
public class Person
{
public string FirstName { get; set; } = string.Empty;
// Omitted for brevity.
}
Bu makalenin devamında göreceğiniz gibi, özel başlatma en çok salt okunur özellikler için kullanışlıdır.
Aşağıda gösterildiği gibi depolama alanını kendiniz de tanımlayabilirsiniz:
public class Person
{
public string? FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
private string? _firstName;
// Omitted for brevity.
}
Özellik uygulaması tek bir ifade olduğunda, alıcı veya ayarlayıcı için ifade gövdeli üyeleri kullanabilirsiniz:
public class Person
{
public string? FirstName
{
get => _firstName;
set => _firstName = value;
}
private string? _firstName;
// Omitted for brevity.
}
Bu basitleştirilmiş söz dizimi, bu makale boyunca uygun olduğunda kullanılacaktır.
Yukarıda gösterilen özellik tanımı bir okuma-yazma özelliğidir. Küme erişimcisindeki anahtar sözcüğüne value
dikkat edin. Erişimcinin set
her zaman adlı value
tek bir parametresi vardır. Erişimci özelliğin get
türüne dönüştürülebilir bir değer döndürmelidir (string
bu örnekte).
Söz diziminin temelleri bunlardır. Çeşitli farklı tasarım deyimlerini destekleyen birçok farklı varyasyon vardır. Şimdi her biri için söz dizimi seçeneklerini keşfedelim ve öğrenelim.
Doğrulama
Yukarıdaki örneklerde, özellik tanımının en basit örneklerinden biri gösterilmiştir: doğrulama içermeyen bir okuma-yazma özelliği. ve set
erişimcilerine get
istediğiniz kodu yazarak birçok farklı senaryo oluşturabilirsiniz.
Bir özellik tarafından temsil edilen değerlerin set
her zaman geçerli olduğundan emin olmak için erişimciye kod yazabilirsiniz. Örneğin, sınıf için bir kuralın Person
adın boş veya boş alan olamaz olduğunu varsayalım. Bunu aşağıdaki gibi yazabilirsiniz:
public class Person
{
public string? FirstName
{
get => _firstName;
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("First name must not be blank");
_firstName = value;
}
}
private string? _firstName;
// Omitted for brevity.
}
Yukarıdaki örnek, özellik ayarlayıcısı doğrulamasının bir parçası olarak bir throw
ifade kullanılarak basitleştirilebilir:
public class Person
{
public string? FirstName
{
get => _firstName;
set => _firstName = (!string.IsNullOrWhiteSpace(value)) ? value : throw new ArgumentException("First name must not be blank");
}
private string? _firstName;
// Omitted for brevity.
}
Yukarıdaki örnek, adın boş veya boşluk olmaması gerektiğini belirten kuralı uygular. Geliştirici yazarsa
hero.FirstName = "";
Bu atama bir ArgumentException
oluşturur. Özellik kümesi erişimcisinin geçersiz dönüş türü olması gerektiğinden, özel durum oluşturarak küme erişimcisinde hataları bildirirsiniz.
Bu söz dizimini senaryonuzda gereken her şeye genişletebilirsiniz. Farklı özellikler arasındaki ilişkileri denetleyebilir veya herhangi bir dış koşula göre doğrulayabilirsiniz. Geçerli C# deyimleri bir özellik erişimcisinde geçerlidir.
Erişim denetimi
Bu noktaya kadar, gördüğünüz tüm özellik tanımları genel erişimcileri olan okuma/yazma özellikleridir. Özellikler için tek geçerli erişilebilirlik bu değildir. Salt okunur özellikler oluşturabilir veya kümeye farklı erişilebilirlik sağlayabilir ve erişimcileri alabilirsiniz. Sınıfınızın Person
yalnızca bu sınıftaki diğer yöntemlerden özelliğinin FirstName
değerini değiştirmeyi etkinleştirmesi gerektiğini varsayalım. Set erişimcisine private
yerine erişilebilirlik public
verebilirsiniz:
public class Person
{
public string? FirstName { get; private set; }
// Omitted for brevity.
}
Artık özelliğine FirstName
herhangi bir koddan erişilebilir, ancak yalnızca sınıfındaki Person
diğer kodlardan atanabilir.
Kümeye herhangi bir kısıtlayıcı erişim değiştirici ekleyebilir veya erişimcileri alabilirsiniz. Bireysel erişimciye yerleştirdiğiniz tüm erişim değiştiriciler, özellik tanımındaki erişim değiştiriciden daha sınırlı olmalıdır. Özelliği olduğundan yukarıdaki yasaldır FirstName
public
, ancak küme erişimcisi şeklindedir private
. Bir erişimci ile public
özellik private
bildiremediniz. Özellik bildirimleri , , internal
protected internal
veya hatta private
bildirilebilirprotected
.
Erişimciye daha kısıtlayıcı değiştirici yerleştirmek de yasaldır get
. Örneğin, bir public
özelliğiniz olabilir, ancak erişimciyi get
ile private
kısıtlayabilirsiniz. Bu senaryo pratikte nadiren gerçekleştirilir.
Salt Okunur
Ayrıca, yalnızca bir oluşturucuda ayarlanabilmesi için bir özellikte yapılan değişiklikleri kısıtlayabilirsiniz. sınıfını Person
aşağıdaki gibi değiştirebilirsiniz:
public class Person
{
public Person(string firstName) => FirstName = firstName;
public string FirstName { get; }
// Omitted for brevity.
}
Yalnızca başlatma
Yukarıdaki örnek, çağıranların parametresini içeren oluşturucuyu FirstName
kullanmasını gerektirir. Çağıranlar, özelliğine bir değer atamak için nesne başlatıcılarını kullanamaz. Başlatıcıları desteklemek için, aşağıdaki kodda gösterildiği gibi erişimciyi bir init
erişimci yapabilirsinizset
:
public class Person
{
public Person() { }
public Person(string firstName) => FirstName = firstName;
public string? FirstName { get; init; }
// Omitted for brevity.
}
Yukarıdaki örnek, bir çağıranın, bu kod özelliğini ayarlamasa bile varsayılan oluşturucuyu kullanarak bir Person
oluşturmasına FirstName
izin verir. C# 11'den başlayarak, arayanların bu özelliği ayarlamasını gerektirebilirsiniz:
public class Person
{
public Person() { }
[SetsRequiredMembers]
public Person(string firstName) => FirstName = firstName;
public required string FirstName { get; init; }
// Omitted for brevity.
}
Yukarıdaki kod, sınıfına Person
iki ekleme yapar. İlk olarak, FirstName
özellik bildirimi değiştiriciyi required
içerir. Bu, yeni Person
bir kod oluşturan tüm kodların bu özelliği ayarlaması gerektiği anlamına gelir. İkincisi, parametre firstName
alan oluşturucu özniteliğine System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute sahiptir. Bu öznitelik, derleyiciye bu oluşturucunun tümrequired
üyeleri ayarlandığını bildirir.
Önemli
Boş değer atanamaz ile karıştırmayınrequired
. bir özelliği null
veya default
olarak ayarlamak required
için geçerlidir. Bu örneklerde olduğu gibi string
tür null atanamazsa, derleyici bir uyarı döndürür.
Çağıranların, aşağıdaki kodda gösterildiği gibi oluşturucuyu ile SetsRequiredMembers
kullanması veya nesne başlatıcı kullanarak özelliğini ayarlaması FirstName
gerekir:
var person = new VersionNinePoint2.Person("John");
person = new VersionNinePoint2.Person{ FirstName = "John"};
// Error CS9035: Required member `Person.FirstName` must be set:
//person = new VersionNinePoint2.Person();
Hesaplanan özellikler
Bir özelliğin yalnızca üye alanının değerini döndürmesi gerekmez. Hesaplanan değer döndüren özellikler oluşturabilirsiniz. Şimdi, ad ve soyadları birleştirilerek hesaplanan tam adı döndürecek şekilde nesnesini genişletelim Person
:
public class Person
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string FullName { get { return $"{FirstName} {LastName}"; } }
}
Yukarıdaki örnekte, tam adın biçimlendirilmiş dizesini oluşturmak için dize ilişkilendirme özelliği kullanılmaktadır.
Hesaplanan özelliği oluşturmak FullName
için daha kısa bir yol sağlayan ifade gövdeli bir üye de kullanabilirsiniz:
public class Person
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string FullName => $"{FirstName} {LastName}";
}
İfade gövdeli üyeler, tek bir ifade içeren yöntemleri tanımlamak için lambda ifadesi söz dizimini kullanır. Burada, bu ifade person nesnesinin tam adını döndürür.
Önbelleğe alınan değerlendirilen özellikler
Hesaplanan özellik kavramını depolama ile karıştırabilir ve önbelleğe alınmış bir değerlendirilmiş özellik oluşturabilirsiniz. Örneğin, dize biçimlendirmesinin FullName
yalnızca ilk kez erişildiğinde olması için özelliğini güncelleştirebilirsiniz:
public class Person
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
private string? _fullName;
public string FullName
{
get
{
if (_fullName is null)
_fullName = $"{FirstName} {LastName}";
return _fullName;
}
}
}
Ancak yukarıdaki kod bir hata içeriyor. Kod veya LastName
özelliğinin FirstName
değerini güncelleştirirse, daha önce değerlendirilen fullName
alan geçersiz olur. alanın yeniden hesaplanacak şekilde ve LastName
özelliğinin fullName
erişimcilerini FirstName
değiştirirsinizset
:
public class Person
{
private string? _firstName;
public string? FirstName
{
get => _firstName;
set
{
_firstName = value;
_fullName = null;
}
}
private string? _lastName;
public string? LastName
{
get => _lastName;
set
{
_lastName = value;
_fullName = null;
}
}
private string? _fullName;
public string FullName
{
get
{
if (_fullName is null)
_fullName = $"{FirstName} {LastName}";
return _fullName;
}
}
}
Bu son sürüm yalnızca gerektiğinde özelliğini değerlendirir FullName
. Önceden hesaplanan sürüm geçerliyse kullanılır. Başka bir durum değişikliği daha önce hesaplanan sürümü geçersiz kılırsa, yeniden hesaplanır. Bu sınıfı kullanan geliştiricilerin uygulamanın ayrıntılarını bilmesi gerekmez. Bu iç değişikliklerin hiçbiri Person nesnesinin kullanımını etkilemez. Bir nesnenin veri üyelerini kullanıma açmak için Özellikleri kullanmanın temel nedeni budur.
Otomatik uygulanan özelliklere öznitelik ekleme
Alan öznitelikleri, otomatik uygulanan özelliklerde derleyici tarafından oluşturulan yedekleme alanına eklenebilir. Örneğin, sınıfına Person
benzersiz bir tamsayı Id
özelliği ekleyen bir düzeltme düşünün. Özelliği otomatik uygulanan bir özellik kullanarak yazarsınız Id
, ancak tasarımınız özelliği kalıcı hale çağırmaz Id
. NonSerializedAttribute yalnızca alanlara eklenebilir, özelliklere eklenemez. Aşağıdaki örnekte gösterildiği gibi özniteliğindeki tanımlayıcıyı field:
kullanarak özelliğinin yedekleme alanına Id
ekleyebilirsinizNonSerializedAttribute:
public class Person
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
[field:NonSerialized]
public int Id { get; set; }
public string FullName => $"{FirstName} {LastName}";
}
Bu teknik, otomatik uygulanan özellikteki yedekleme alanına eklediğiniz tüm öznitelikler için çalışır.
INotifyPropertyChanged Uygulama
Özellik erişimcisinde kod yazmanız gereken son senaryo, veri bağlama istemcilerine bir değerin INotifyPropertyChanged değiştiğini bildirmek için kullanılan arabirimi desteklemektir. Bir özelliğin değeri değiştiğinde, nesne değişikliği göstermek için olayı tetikler INotifyPropertyChanged.PropertyChanged . Veri bağlama kitaplıkları da bu değişikliğe göre görüntü öğelerini güncelleştirir. Aşağıdaki kod, bu kişi sınıfının özelliği için FirstName
nasıl uygulayabileceğinizi INotifyPropertyChanged
gösterir.
public class Person : INotifyPropertyChanged
{
public string? FirstName
{
get => _firstName;
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("First name must not be blank");
if (value != _firstName)
{
_firstName = value;
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(nameof(FirstName)));
}
}
}
private string? _firstName;
public event PropertyChangedEventHandler? PropertyChanged;
}
işleci ?.
null koşullu işleç olarak adlandırılır. İşlecin sağ tarafını değerlendirmeden önce null başvuruyu denetler. Sonuç, olayın abonesi PropertyChanged
yoksa olayı tetikleyen kodun yürütülmeyecek olmasıdır. Bu durumda bu çek olmadan bir NullReferenceException
çek oluşturur. Daha fazla bilgi için bkz. events
. Bu örnek ayrıca özellik adı simgesinden metin gösterimine dönüştürmek için yeni nameof
işlecini kullanır. özelliğini nameof
kullanmak, özelliğin adını yanlış yazdığınız hataları azaltabilir.
Yine uygulamak INotifyPropertyChanged , ihtiyacınız olan senaryoları desteklemek için erişimcilerinize kod yazabileceğiniz bir örnektir.
Toplama
Özellikler, bir sınıf veya nesnedeki akıllı alanların bir biçimidir. Nesnenin dışından, nesnedeki alanlar gibi görünürler. Ancak, özellikler C# işlevselliğinin tam paleti kullanılarak uygulanabilir. Doğrulama, farklı erişilebilirlik, gecikmeli değerlendirme veya senaryolarınızın ihtiyaç duyduğu gereksinimleri sağlayabilirsiniz.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin