Aracılığıyla paylaş


Kısmi özellikler

Uyarı

Bu makale bir özellik belirtimidir. Belirtim, özelliğin tasarım belgesi olarak görev alır. Önerilen belirtim değişikliklerini ve özelliğin tasarımı ve geliştirilmesi sırasında gereken bilgileri içerir. Bu makaleler, önerilen belirtim değişiklikleri son haline getirilene ve geçerli ECMA belirtimine dahil edilene kadar yayımlanır.

Özellik belirtimi ile tamamlanan uygulama arasında bazı tutarsızlıklar olabilir. Bu farklılıklar ilgili dil tasarım toplantısı (LDM) notlarında yakalanır.

Özellik belirtimlerini C# dil standardına benimseme işlemi hakkında daha fazla bilgi edinmek içinbelirtimleri makalesinde bulabilirsiniz.

Şampiyonluk sorunu: https://github.com/dotnet/csharplang/issues/6420

Dilbilgisi

property_declaration dil bilgisi (§14.7.1) aşağıdaki gibi güncelleştirilir:

property_declaration
-    : attributes? property_modifier* type member_name property_body
+    : attributes? property_modifier* 'partial'? type member_name property_body
    ;  

Açıklamalar: Bu, method_header(§15.6.1) ve class_declaration(§15.2.1) nasıl belirtildiğine biraz benzer. ( Sorun #946'nın sipariş gereksinimini gevşetmeyi önerdiğini ve büyük olasılıkla değiştiriciye izin partial veren tüm bildirimler için geçerli olacağını unutmayın. Yakın gelecekte böyle bir sıralama rahatlaması belirtmeyi ve bu özelliğin uygulandığı sürümde uygulamayı planlıyoruz.)

Bildirimleri tanımlama ve uygulama

Bir özellik bildirimi kısmi değiştirici içerdiğinde, bu özelliğin kısmi bir özellik olduğu söylenir. Kısmi özellikler yalnızca kısmi türlerin üyesi olarak bildirilebilir.

Kısmi özellik bildiriminin, erişimcilerinin tümü noktalı virgül gövdelerine sahip olduğunda ve değiştiricisi olmadığında tanımlayıcı bir extern olduğu söylenir. Aksi takdirde, uygulayıcı bildirimdir.

partial class C
{
    // Defining declaration
    public partial string Prop { get; set; }

    // Implementing declaration
    public partial string Prop { get => field; set => field = value; }
}

Tanımlayıcı bildirim için bozulmamış formu noktalı virgül erişimci gövdeleriyle ayırdığımız için kısmi bir özellik otomatik olarak uygulanamaz. Bu nedenle Otomatik uygulanan özellikleri (§15.7.4) aşağıdaki gibi ayarlarız:

Otomatik olarak uygulanan bir özellik (veya kısaca otomatik özellik), yalnızca noktalı virgül erişimci gövdelerine sahip soyut olmayan, extern olmayan, kısmi olmayan, ref değeri olmayan bir özelliktir.

Açıklamalar. Derleyicinin tek bir bildirime yalıtılarak bakabilmesi ve bunun bir tanımlayıcı mı yoksa uygulayan bir bildirim mi olduğunu bilebilmesi yararlıdır. Bu nedenle, örneğin iki özdeş partial özellik bildirimi ekleyerek otomatik özelliklere izin vermek istemiyoruz. Bu özelliğin kullanım örneklerinin kısmi özelliği bir otomatik özellik ile uygulamayı içerdiğini düşünmüyoruz, ancak önemsiz bir uygulamanın istendiği durumlarda anahtar sözcüğün field işleri yeterince basit hale getirdiğini düşünüyoruz.


Kısmi bir özelliğin bir tanımlayıcı bildirimi ve uygulayan bildirimi olmalıdır.

Açıklamalar. Ayrıca, bildirimin ikiden fazla bölüme bölünmesine izin vermenin, örneğin farklı yerlerde farklı erişimcilerin uygulanmasına izin vermenin yararlı olduğunu da düşünmüyoruz. Bu nedenle, kısmi yöntemlerle oluşturulan şemayı taklit ediyoruz.


Yalnızca kısmi bir özelliğin tanımlama bildirimi, yalnızca kısmi bir yöntemin tanımlama bildiriminin aşırı yükleme çözümlemesine katılmasına benzer şekilde aramaya katılır.

Açıklamalar. Derleyicide üye listesinde yalnızca tanımlama bildirimi simgesinin görünmesini ve uygulayan bölümün simgesine tanımlama simgesi aracılığıyla erişilebileceğini bekleriz. Ancak, null atanabilir analiz gibi bazı özellikler, daha kullanışlı bir davranış sağlamak için uygulama bildirimini görebilir.

partial class C
{
    public partial string Prop { get; set; }
    public partial string Prop { get => field; set => field = value; }

    public C() // warning CS8618: Non-nullable property 'Prop' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
    {
    }
}

Kısmi bir özelliğin değiştiriciye abstract sahip olmasına izin verilmez.

Kısmi bir özellik, arabirim özelliklerini açıkça uygulayamaz.

Öznitelik birleştirme

Kısmi yöntemlere benzer şekilde, sonuçta elde edilen özellikteki öznitelikler parçaların birleştirilmiş öznitelikleri belirtilmeyen bir sırada birleştirilir ve yinelenenler kaldırılmaz.

Arayan-bilgi öznitelikleri

Aşağıdaki dili standarttan ayarlarız:

Kısmi yöntem üye bildiriminin hem tanımlama hem de uygulama bölümünün parametresinde aynı caller-info özniteliğine sahip olmak bir hatadır. Yalnızca tanımlama bölümündeki caller-info öznitelikleri uygulanırken, yalnızca uygulayan bölümde oluşan caller-info öznitelikleri yoksayılır.

  • Açıklanan hata, sahip olmayan AllowMultiple = truebu özniteliklerin tanımlarından kaynaklanır. Kısmi bildirimler de dahil olmak üzere bunları birden çok kez kullanmak hatayla sonuçlanır.
  • Çağıran-bilgi öznitelikleri kısmi bir yöntemin uygulama bölümündeki bir parametreye uygulandığında, Roslyn derleyicisi bir uyarı bildirir. Ayrıca kısmi bir özellikte aynı senaryo için bir uyarı bildirir.

Eşleşen imzalar

14 Eylül 2020'de yapılan LDM toplantısında, uyarı dalgasında ortaya çıkan kısmi yöntemlerin imza eşleştirmesi için bir dizi "katı" gereksinim tanımlandı. Kısmi özellikler, mümkün olduğunca imza eşleştirme için kısmi yöntemlere benzer gereksinimlere sahiptir, ancak uyuşmazlık için tüm tanılamalar varsayılan olarak raporlanır ve bir uyarı dalgasının arkasında tutulmaz.

İmza eşleştirme gereksinimleri şunlardır:

  1. Çalışma zamanı için önemli olan kısmi özellik bildirimleri arasındaki tür ve başvuru türü farklılıkları derleme zamanı hatasıyla sonuçlanır.
  2. Kısmi özellik bildirimleri içindeki tanımlama grubu öğesi adlarındaki farklar, kısmi yöntemlerle aynı derleme zamanı hatasına neden olur.
  3. Özellik bildirimleri ve erişimci bildirimleri aynı değiştiricilere sahip olmalıdır, ancak değiştiriciler farklı bir sırada görünebilir.
    • Özel durum: Bu, yalnızca uygulayan bir extern görünebilen değiştirici için geçerli değildir.
  4. Kısmi özellik bildirimlerinin imzalarındaki diğer tüm bozulmalar, aşağıdaki özel durumlarla birlikte derleme zamanı uyarısına neden olur:
    • Kısmi özellik bildirimlerindeki veya içindeki öznitelik listelerinin eşleşmesi gerekmez. Bunun yerine özniteliklerin karşılık gelen konumlarda birleştirilmesi, Öznitelik birleştirme başına gerçekleştirilir.
    • Boş değer atanabilir bağlam farklılıkları uyarılara neden olmaz. Başka bir deyişle, türlerden birinin null atanabilir-belirsiz olduğu ve diğer türün null atanabilir-açıklamalı veya null atanamaz-açıklamalı olduğu bir fark herhangi bir uyarıya neden olmaz.
    • Varsayılan parametre değerlerinin eşleşmesi gerekmez. Kısmi dizin oluşturucunun uygulama bölümünde varsayılan parametre değerleri olduğunda bir uyarı bildirilir. Bu, kısmi bir yöntemin uygulama bölümü varsayılan parametre değerlerine sahip olduğunda oluşan mevcut bir uyarıya benzer.
  5. Parametre adları bildirimleri tanımlama ve uygulama arasında farklılık gösterdiğinde bir uyarı oluşur. Tanım bölümündeki parametre adları kullanım sitelerinde ve yaymada kullanılır.
  6. Belirsiz null atanabilirlik içermeyen null atanabilirlik farklılıkları uyarılarla sonuçlanır. Erişimci gövdesi analiz edilirken uygulama parçası imzası kullanılır. Tanım bölümü imzası, kullanım siteleri analiz edilirken ve yaymada kullanılır. Bu, kısmi yöntemlerle tutarlıdır.
partial class C1
{
    public partial string Prop { get; private set; }

    // Error: accessor modifier mismatch in 'set' accessor of 'Prop'
    public partial string Prop { get => field; set => field = value; }
}

partial class C2
{
    public partial string Prop { get; init; }

    // Error: implementation of 'Prop' must have an 'init' accessor to match definition
    public partial string Prop { get => field; set => field = value; }
}

partial class C3
{
    public partial string Prop { get; }

    // Error: implementation of 'Prop' cannot have a 'set' accessor because the definition does not have a 'set' accessor.
    public partial string Prop { get => field; set => field = value; }
}

partial class C4
{
    public partial string this[string s = "a"] { get; set; }
    public partial string this[string s] { get => s; set { } } // ok

    public partial string this[int i, string s = "a"] { get; set; }
    public partial string this[int i, string s = "a"] { get => s; set { } } // CS1066: The default value specified for parameter 's' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
}

Dökümantasyon yorumları

Kısmi özelliklerle ilgili belge açıklamalarının davranışının, kısmi yöntemler için sevk ettiğimiz yöntemle tutarlı olmasını istiyoruz. Bu davranış içinde https://github.com/dotnet/csharplang/issues/5193ayrıntılı olarak anlatılır.

Kısmi bir özelliğin tanımına veya uygulama bölümüne belge açıklamaları eklemeye izin verilir. (Belge açıklamalarının özellik erişimcilerinde desteklenmediğini unutmayın.)

Belge açıklamaları özelliğin yalnızca bir parçasında mevcut olduğunda, bu belge açıklamaları normal olarak kullanılır (belge ISymbol.GetDocumentationCommentXml()XML dosyasına yazılan aracılığıyla gösterilir).

Her iki bölümde de belge açıklamaları olduğunda, tanım bölümündeki tüm belge açıklamaları bırakılır ve yalnızca uygulama bölümündeki belge açıklamaları kullanılır.

Örneğin, aşağıdaki program:

/// <summary>
/// My type
/// </summary>
partial class C
{
    /// <summary>Definition part comment</summary>
    /// <returns>Return value comment</returns>
    public partial int Prop { get; set; }
    
    /// <summary>Implementation part comment</summary>
    public partial int Prop { get => 1; set { } }
}

Aşağıdaki XML belge dosyasının sonuçları:

<?xml version="1.0"?>
<doc>
    <assembly>
        <name>ConsoleApp1</name>
    </assembly>
    <members>
        <member name="T:C">
            <summary>
            My type
            </summary>
        </member>
        <member name="P:C.Prop">
            <summary>
            Implementation part comment
            </summary>
        </member>
    </members>
</doc>

Parametre adları kısmi bildirimler arasında farklılık gösterdiğinde, <paramref> öğeler kaynak koddaki belge açıklamasıyla ilişkili bildirimden parametre adlarını kullanır. Örneğin, uygulama bildirimine yerleştirilen bir belge açıklamasındaki paramref, parametre adlarını kullanarak uygulama bildirimindeki parametre simgelerine başvurur. Bu, kısmi yöntemlerle tutarlıdır.

/// <summary>
/// My type
/// </summary>
partial class C
{
    public partial int this[int x] { get; set; }

    /// <summary>
    /// <paramref name="x"/> // warning CS1734: XML comment on 'C.this[int]' has a paramref tag for 'x', but there is no parameter by that name
    /// <paramref name="y"/> // ok. 'Go To Definition' will go to 'int y'.
    /// </summary>
    public partial int this[int y] { get => 1; set { } } // warning CS9256: Partial property declarations 'int C.this[int x]' and 'int C.this[int y]' have signature differences.
}

Aşağıdaki XML belge dosyasının sonuçları:

<?xml version="1.0"?>
<doc>
    <assembly>
        <name>ConsoleApp1</name>
    </assembly>
    <members>
        <member name="T:C">
            <summary>
            My type
            </summary>
        </member>
        <member name="P:C.Item(System.Int32)">
            <summary>
            <paramref name="x"/> // warning CS1734: XML comment on 'C.this[int]' has a paramref tag for 'x', but there is no parameter by that name
            <paramref name="y"/> // ok. 'Go To Definition' will go to 'int y'.
            </summary>
        </member>
    </members>
</doc>

Meta veri imzası tanım bölümünden parametre adlarını kullanacağından bu durum kafa karıştırıcı olabilir. Bu karışıklığı önlemek için parametre adlarının bölümler arasında eşleştiğinden emin olunması önerilir.

Dizinleyiciler

2 Kasım 2022'de LDM toplantısı başına dizin oluşturucular bu özellik ile desteklenecektir.

Dizin oluşturucu dil bilgisi aşağıdaki gibi değiştirilir:

indexer_declaration
-    : attributes? indexer_modifier* indexer_declarator indexer_body
+    : attributes? indexer_modifier* 'partial'? indexer_declarator indexer_body
-    | attributes? indexer_modifier* ref_kind indexer_declarator ref_indexer_body
+    | attributes? indexer_modifier* 'partial'? ref_kind indexer_declarator ref_indexer_body
    ;

Kısmi dizin oluşturucu parametreleri, Eşleşen imzalarla aynı kurallar başına bildirimler arasında eşleşmelidir. Öznitelik birleştirme , kısmi dizin oluşturucu parametreleri arasında gerçekleştirilir.

partial class C
{
    public partial int this[int x] { get; set; }
    public partial int this[int x]
    {
        get => this._store[x];
        set => this._store[x] = value;
    }
}

// attribute merging
partial class C
{
    public partial int this[[Attr1] int x]
    {
        [Attr2] get;
        set;
    }

    public partial int this[[Attr3] int x]
    {
        get => this._store[x];
        [Attr4] set => this._store[x] = value;
    }

    // results in a merged member emitted to metadata:
    public int this[[Attr1, Attr3] int x]
    {
        [Attr2] get => this._store[x];
        [Attr4] set => this._store[x] = value;
    }
}

Açık Sorunlar

Diğer üye türleri

Topluluk üyesi, kısmi olaylar için destek istemek üzere bir tartışma açtı. 2 Kasım 2022'deki LDM toplantısında, kısmen o sırada kimse talep etmediğinden etkinlikler için destek istemeye karar verdik. Bu istek geldiğinden ve en son tartıştığımız tarihten bu yana bir yıldan fazla zaman geçmesine rağmen bu soruyu yeniden ziyaret etmek isteyebiliriz.

Oluşturucuların, işleçlerin, alanların vb. kısmi bildirimlerine izin verme konusunda daha da ileri gidebiliriz, ancak zaten kısmi özellikler yaptığımız için bunların tasarım yükünün haklı olup olmadığı belirsizdir.