Sdílet prostřednictvím


Částečné vlastnosti

Poznámka

Tento článek je specifikace funkce. Specifikace slouží jako návrhový dokument pro funkci. Zahrnuje navrhované změny specifikace spolu s informacemi potřebnými při návrhu a vývoji funkce. Tyto články se publikují, dokud nebudou navrhované změny specifikace finalizovány a začleněny do aktuální specifikace ECMA.

Mezi specifikací funkce a dokončenou implementací může docházet k nějakým nesrovnalostem. Tyto rozdíly jsou zachyceny v příslušných poznámkách schůzce návrhu jazyka (LDM).

Další informace o procesu přijetí specifikací funkcí do jazyka C# najdete v článku o specifikacích .

Problém šampiona: https://github.com/dotnet/csharplang/issues/6420

Gramatika

gramatiky property_declaration (§14.7.1) se aktualizuje následujícím způsobem:

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

poznámky: Je to trochu podobné tomu, jak jsou uvedeny method_header(§15.6.1) a class_declaration(§15.2.1). (Všimněte si, že Vydání č. 946 navrhuje zmírnit požadavek řazení a pravděpodobně by se použil na všechny deklarace, které umožňují modifikátor partial. V blízké budoucnosti plánujeme určit takové uvolnění objednávek a implementovat ho ve stejné verzi, ve které je tato funkce implementovaná.)

Definování a implementace deklarací

Pokud deklarace vlastnosti obsahuje částečný modifikátor, znamená to, že vlastnost je částečná vlastnost. Částečné vlastnosti mohou být deklarovány pouze jako členy částečných typů.

částečná vlastnost deklarace je definující deklaraci, pokud jeho příslušenství mají středníky a chybí extern modifikátor. Jinak se jedná o prováděcí deklaraci.

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

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

Vzhledem k tomu, že jsme pro definující deklaracirezervovali syntaktický tvar se středníkem , nelze částečnou vlastnost automaticky implementovat. Proto upravíme automaticky implementované vlastnosti (§15.7.4) následujícím způsobem:

Automaticky implementovaná vlastnost (nebo automatická vlastnost pro short) je ne abstraktní, neintertraktní, nestrukturovaná nečástečně nefakturovaná vlastnost s nástavci pouze středníkem.

Poznámky. Kompilátor je užitečný, aby se mohl podívat na jednu deklaraci izolovaně a zjistit, jestli se jedná o definici nebo implementační deklaraci. Proto nepovolíme automatické vlastnosti tím, že zahrneme dvě identické deklarace partial vlastností, například. Nemyslíme si, že případy použití této funkce zahrnují implementaci částečné vlastnosti s automatickou vlastností, ale v případech, kdy je požadovaná triviální implementace, si myslíme, že field klíčové slovo dělá věci dostatečně jednoduché.


Částečná vlastnost musí mít jednu definující deklaraci a jednu implementaci deklarace.

Poznámky. Také si nemysleme, že je užitečné povolit rozdělení deklarace mezi více než dvě části, aby bylo možné implementovat různé přístupové objekty na různých místech, například. Proto jednoduše napodobujeme schéma zavedené částečnými metodami.


Vyhledávání se účastní pouze definice částečné vlastnosti, podobně jako definice deklarace částečné metody, která se podílí na řešení přetížení.

Poznámky. V kompilátoru bychom očekávali, že se v seznamu členů zobrazí pouze symbol definující deklarace a symbol pro implementační část bude přístupný prostřednictvím definujícího symbolu. Některé funkce, jako je analýza s možnou hodnotou null, ale můžou vidět prostřednictvím k implementaci deklarace, aby bylo možné poskytovat užitečnější chování.

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.
    {
    }
}

Částečná vlastnost nemá povolený modifikátor abstract.

Částečná vlastnost nemůže explicitně implementovat vlastnosti rozhraní.

Slučování atributů

Podobně jako částečné metody jsou atributy ve výsledné vlastnosti zřetězením kombinovaných atributů částí v nespecifikovaném pořadí a duplicity nejsou odebrány.

Atributy informace o volajícím

Upravujeme následující jazyk ze standardu :

Jedná se o chybu mít stejný atribut s informacemi o volajícím na parametru jak ve definující, tak v implementační části částečné metody v deklaraci člena. Použijí se pouze atributy informací o volajícím v definující části, zatímco atributy informací o volajícím, ke kterým dochází pouze v implementující části, se ignorují.

  • Popsaná chyba spadá mimo definice těchto atributů, které nemají AllowMultiple = true. Pokud je použijete vícekrát, včetně částečných deklarací, dojde k chybě.
  • Pokud jsou atributy caller-info použity na parametr v části implementace částečné metody, kompilátor Roslyn hlásí upozornění. Zobrazí se také upozornění pro stejný scénář v rámci částečných vlastností.

Odpovídající podpisy

Zasedání LDM dne 14. září 2020 definovalo sadu "striktních" požadavků na shodu podpisů částečných metod, které byly zavedeny ve výstražné vlně. Částečné vlastnosti mají obdobné požadavky jako částečné metody pro porovnávání podpisů tak, jak je to možné, s tím rozdílem, že veškerá diagnostika neshod je ve výchozím nastavení hlášena a není skryta za vlnou upozornění.

Mezi požadavky na porovnávání podpisů patří:

  1. Rozdíly typu a ref kind mezi částečnými deklaracemi vlastností, které jsou významné pro výsledek při běhu, způsobí chybu při kompilaci.
  2. Rozdíly v názvech elementů řazené kolekce členů v rámci částečných deklarací vlastností mají za následek chybu v době kompilace, která je stejná jako u částečných metod.
  3. Deklarace vlastností a jejich deklarace příslušenství musí mít stejné modifikátory, ačkoli modifikátory mohou být uvedeny v jiném pořadí.
    • Výjimka: Toto se nevztahuje na modifikátor extern, který se může objevit pouze na prováděcí deklaraci.
  4. Všechny ostatní syntaktické rozdíly v podpisech částečných deklarací vlastností vedou k upozornění v době kompilace s následujícími výjimkami:
    • Seznamy atributů u nebo v rámci částečných deklarací vlastností se nemusí shodovat. Místo toho se sloučení atributů na odpovídajících pozicích provádí podle Sloučení atributů.
    • Rozdíly kontextu s možnou hodnotou null nezpůsobí upozornění. Jinými slovy, rozdíl, kdy jeden z typů je ignorující hodnotu null a druhý typ je buď označený jako nullable nebo označený jako not-nullable, nevyvolá žádná upozornění.
    • Výchozí hodnoty parametrů se nemusí shodovat. Pokud má část implementace částečného indexeru výchozí hodnoty parametrů, zobrazí se upozornění. Podobá se existujícímu upozornění, ke kterému dochází v případě, že část implementace částečné metody má výchozí hodnoty parametrů.
  5. K upozornění dochází, když se názvy parametrů liší v definování a implementaci deklarací. Názvy parametrů z části definice se používají na místech použití a generují hodnoty.
  6. Rozdíly s nulovostí, které nezahrnují obživnou hodnotu null, vedou k upozorněním. Při analýze těla příslušenství se použije podpis části implementace. Podpis části definice se používá při analýze míst použití a generování. To odpovídá částečným metodám.
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
}

Komentáře k dokumentaci

Chceme, aby chování komentářů k dokumentaci k částečným vlastnostem bylo konzistentní s tím, co jsme uvedli pro částečné metody. Toto chování je podrobně popsáno v https://github.com/dotnet/csharplang/issues/5193.

Je povoleno zahrnout komentáře dokumentu k definici nebo implementaci části částečné vlastnosti. (Poznámka: Komentáře k dokumentu nejsou u přístupových metod podporované.)

Pokud jsou komentáře k dokumentu k dispozici pouze na jedné z částí vlastnosti, tyto komentáře dokumentu se používají normálně (zobrazí se prostřednictvím ISymbol.GetDocumentationCommentXml(), zapsány do souboru XML dokumentace atd.).

Když se komentáře k dokumentu nacházejí na obou částech, všechny komentáře k dokumentu v definici se zahodí a použijí se jenom komentáře k dokumentaci k implementační části.

Například následující 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 { } }
}

Výsledkem je následující soubor dokumentace XML:

<?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>

Pokud se názvy parametrů liší mezi částečnými deklaracemi, <paramref> prvky používají názvy parametrů z deklarace přidružené k komentáři dokumentace ve zdrojovém kódu. Například paramref v komentáři dokumentace umístěný v implementující deklaraci odkazuje na symboly parametrů implementující deklarace s použitím jejich jmen parametrů. To odpovídá částečným metodám.

/// <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.
}

Výsledkem je následující soubor dokumentace XML:

<?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>

To může být matoucí, protože podpis metadat použije názvy parametrů z části definice. Doporučujeme zajistit, aby se názvy parametrů shodovaly napříč částmi, aby nedocházelo k tomuto nejasnostem.

Indexování

Na schůzce LDM dne 2. listopadu 2022budou indexátoři podporováni touto funkcí.

Gramatika indexerů se upraví takto:

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
    ;

Částečné parametry indexeru se musí shodovat s deklaracemi podle stejných pravidel jako odpovídající podpisy. Sloučení atributů se provádí napříč částečnými parametry indexeru.

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;
    }
}

Otevřené problémy

Jiné druhy členů

Člen komunity otevřel diskuzi s žádostí o podporu částečných událostí. V zasedání LDM dne 2. listopadu 2022jsme se rozhodli odložit podporu akcí, a to částečně proto, že o ni v té době nikdo nepožádal. Můžeme se k této otázce vrátit, protože tato žádost přišla a od posledního diskutování už uplynulo více než rok.

Mohli bychom také jít ještě dál a povolit částečné deklarace konstruktorů, operátorů, polí atd., ale není jasné, zda je návrhová zátěž těchto prvků odůvodněná, jenom proto, že už umožňujeme částečné vlastnosti.