Gedeeltelijke eigenschappen
Notitie
Dit artikel is een functiespecificatie. De specificatie fungeert als het ontwerpdocument voor de functie. Het bevat voorgestelde specificatiewijzigingen, samen met informatie die nodig is tijdens het ontwerp en de ontwikkeling van de functie. Deze artikelen worden gepubliceerd totdat de voorgestelde specificaties zijn voltooid en opgenomen in de huidige ECMA-specificatie.
Er kunnen enkele verschillen zijn tussen de functiespecificatie en de voltooide implementatie. Deze verschillen worden vastgelegd in de belangrijke LDM-notities (Language Design Meeting).
Meer informatie over het proces voor het aannemen van functiespeclets in de C#-taalstandaard vindt u in het artikel over de specificaties.
Probleem met kampioen: https://github.com/dotnet/csharplang/issues/6420
De property_declaration grammatica (§14.7.1) wordt als volgt bijgewerkt:
property_declaration
- : attributes? property_modifier* type member_name property_body
+ : attributes? property_modifier* 'partial'? type member_name property_body
;
Opmerkingen: dit lijkt enigszins op de manier waarop method_header(§15.6.1) en class_declaration(§15.2.1) worden opgegeven. (Houd er rekening mee dat Issue #946 voorstelt om de volgordevereiste te versoepelen, en waarschijnlijk van toepassing is op alle verklaringen die de partial
modifier toestaan. We zijn van plan om een dergelijke versoepeling van de volgorde in de nabije toekomst vast te leggen en deze te implementeren in dezelfde release als de functie zelf.)
Wanneer een eigenschapdeclaratie een gedeeltelijke modifier bevat, is die eigenschap een gedeeltelijke eigenschap. Gedeeltelijke eigenschappen kunnen alleen worden gedeclareerd als leden van gedeeltelijke typen.
Een gedeeltelijke eigenschap verklaring wordt een definiërende verklaring genoemd wanneer de accessors allemaal puntkomma-lichamen hebben en de extern
modificator ontbreekt. Anders is het een implementerende declaratie.
partial class C
{
// Defining declaration
public partial string Prop { get; set; }
// Implementing declaration
public partial string Prop { get => field; set => field = value; }
}
Omdat we het syntactische formulier hebben gereserveerd met semikommatoegangsorganen voor de het definiëren van declaraties, kan een gedeeltelijke eigenschap niet automatisch worden geïmplementeerd. Daarom passen we automatisch geïmplementeerde eigenschappen (§15.7.4) als volgt aan:
Een automatisch geïmplementeerde eigenschap (of auto-eigenschap voor kort), is een niet-abstracte, niet-externe, niet-partiële, niet-ref-waarde-eigenschap met toegangslichaam enkel met puntkomma's.
opmerkingen. Het is handig voor de compiler om één declaratie geïsoleerd te bekijken en te weten of het een definiërende of een uitvoeringsdeclaratie is. Daarom willen we geen automatische eigenschappen toestaan door bijvoorbeeld twee identieke partial
eigenschappendeclaraties op te geven. We denken niet dat de use cases voor deze functie betrekking hebben op het implementeren van de gedeeltelijke eigenschap met een automatische eigenschap, maar in gevallen waarin een triviale implementatie gewenst is, denken we dat het trefwoord field
het eenvoudig genoeg maakt.
Een gedeeltelijke eigenschap moet één declaratie definiëren en één declaratie.
opmerkingen. We vinden het ook niet handig om de declaratie over meer dan twee delen te splitsen, zodat verschillende toegangsrechten op verschillende plaatsen kunnen worden geïmplementeerd, bijvoorbeeld. Daarom imiteren we gewoon het schema dat door gedeeltelijke methoden is vastgesteld.
Alleen de definiërende declaratie van een gedeeltelijke eigenschap neemt deel aan de zoekactie, vergelijkbaar met hoe alleen de definiërende declaratie van een gedeeltelijke methode deelneemt aan overbelastingsresolutie.
opmerkingen. In de compiler verwachten we dat alleen het symbool voor de definiërende declaratie wordt weergegeven in de ledenlijst en dat het symbool voor het implementatieonderdeel toegankelijk is via het definiërende symbool. Sommige functies zoals een null-analyse kunnen echter door zien bij de implementatiedeclaratie om nuttiger gedrag te bieden.
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.
{
}
}
Een gedeeltelijke eigenschap mag de “abstract
modifier” niet hebben.
Een gedeeltelijke eigenschap kan interface-eigenschappen niet expliciet implementeren.
Net als bij gedeeltelijke methoden zijn de kenmerken in de resulterende eigenschap de gecombineerde kenmerken van de onderdelen samengevoegd in een niet-opgegeven volgorde en worden duplicaten niet verwijderd.
We passen de volgende taal aan op basis van de standaard:
Het is een fout om hetzelfde caller-info attribuut te hebben op een parameter van zowel het definiërende als het implementerende deel van een gedeeltelijke
methodlid declaratie. Alleen kenmerken van de aanroeper-info in het definiërende onderdeel worden toegepast, terwijl kenmerken van aanroepergegevens die alleen in het implementatieonderdeel optreden, worden genegeerd.
- De beschreven fout valt buiten de definities van deze kenmerken die geen
AllowMultiple = true
hebben. Als u ze meerdere keren gebruikt, inclusief gedeeltelijke declaraties, resulteert dit in een fout. - Wanneer aanroeper-infokenmerken worden toegepast op een parameter in het implementatiegedeelte van een gedeeltelijke methode, rapporteert de Roslyn-compiler een waarschuwing. Er wordt ook een waarschuwing voor hetzelfde scenario in een gedeeltelijke eigenschap weergegeven.
De LDM-vergadering op 14 september 2020 heeft een reeks "strikte" vereisten gedefinieerd voor het overeenkomen van handtekeningen van gedeeltelijke methoden, die zijn geïntroduceerd als onderdeel van een waarschuwingsgolf. Gedeeltelijke eigenschappen hebben vergelijkbare eisen als gedeeltelijke methoden voor het zoveel mogelijk laten overeenkomen van signaturen. Echter, alle mismatching-diagnoses worden standaard gerapporteerd en worden niet verborgen achter een waarschuwing.
Vereisten voor handtekeningkoppeling zijn onder andere:
- Type- en referentiesoortverschillen tussen gedeeltelijke eigenschapsdeclaraties die de runtime beïnvloeden, resulteren in een compilatiefout.
- Verschillen in tuple-elementnamen in gedeeltelijke eigenschapsdeclaraties resulteert in een compilatiefout, hetzelfde als voor gedeeltelijke methoden.
- De eigenschappendeclaraties en de bijbehorende declaraties moeten dezelfde modifiers hebben, hoewel de modifiers in een andere volgorde kunnen worden weergegeven.
- Uitzondering: dit geldt niet voor de
extern
modificator, die alleen kan voorkomen bij een implementerende declaratie.
- Uitzondering: dit geldt niet voor de
- Alle andere syntactische verschillen in de handtekeningen van gedeeltelijke eigenschapsdeclaraties resulteren in een waarschuwing over de compilatietijd, met de volgende uitzonderingen:
- Kenmerklijsten op of binnen gedeeltelijke eigenschapsdeclaraties hoeven niet overeen te komen. In plaats daarvan wordt het samenvoegen van kenmerken in bijbehorende posities uitgevoerd, per kenmerk samenvoegen.
- Verschillen in null-context veroorzaken geen waarschuwingen. Met andere woorden, een verschil waarbij een van de typen nullable-onbewust is, en het andere type null-gemarkeerd of niet-null-gemarkeerd is, resulteert niet in waarschuwingen.
- Standaardparameterwaarden hoeven niet overeen te komen. Er wordt een waarschuwing gerapporteerd wanneer het implementatiegedeelte van een gedeeltelijke indexeerfunctie standaardparameterwaarden heeft. Dit is vergelijkbaar met een bestaande waarschuwing die optreedt wanneer het implementatiegedeelte van een gedeeltelijke methode standaardparameterwaarden heeft.
- Er wordt een waarschuwing weergegeven wanneer parameternamen verschillen tussen het definiëren en implementeren van declaraties. De parameternamen van het definitieonderdeel worden gebruikt bij gebruikssites en in emit.
- Verschillen in nullabiliteit die geen niet-zichtbare nullabiliteit inhouden, resulteren in waarschuwingen. Bij het analyseren van een hoofdtekst van een accessor wordt de handtekening van het implementatieonderdeel gebruikt. De handtekening van het definitieonderdeel wordt gebruikt bij het analyseren van gebruikssites en bij verzenden. Dit is consistent met gedeeltelijke methoden.
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
}
We willen dat het gedrag van documentopmerkingen over gedeeltelijke eigenschappen consistent is met wat we hebben verzonden voor gedeeltelijke methoden. Dat gedrag wordt beschreven in https://github.com/dotnet/csharplang/issues/5193.
Het is toegestaan documentopmerkingen op te nemen over de definitie of implementatie van een gedeeltelijke eigenschap. (Houd er rekening mee dat documentatie-opmerkingen niet worden ondersteund voor eigenschapstoegangsmethoden.)
Wanneer documentopmerkingen aanwezig zijn op slechts één van de onderdelen van de eigenschap, worden deze documentopmerkingen normaal gebruikt (weergegeven via ISymbol.GetDocumentationCommentXml()
, weggeschreven naar het XML-documentatiebestand, enzovoort).
Wanneer documentopmerkingen op beide onderdelen aanwezig zijn, worden alle documentopmerkingen in het definitieonderdeel verwijderd en worden alleen de opmerkingen van het document in het implementatieonderdeel gebruikt.
Bijvoorbeeld het volgende programma:
/// <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 { } }
}
Resultaten in het volgende XML-documentatiebestand:
<?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>
Wanneer parameternamen verschillen tussen gedeeltelijke declaraties, gebruiken <paramref>
elementen de parameternamen uit de declaratie die is gekoppeld aan de opmerking bij de documentatie in broncode. Een paramref op een doc-opmerking die is geplaatst op een implementatiedeclaratie verwijst bijvoorbeeld naar de parametersymbolen in de implementatiedeclaratie met behulp van de parameternamen. Dit is consistent met gedeeltelijke methoden.
/// <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.
}
Resultaten in het volgende XML-documentatiebestand:
<?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>
Dit kan verwarrend zijn, omdat de metagegevenshandtekening parameternamen uit het definitieonderdeel gebruikt. Het wordt aanbevolen om ervoor te zorgen dat parameternamen overeenkomen met alle onderdelen om deze verwarring te voorkomen.
Per LDM vergadering op 2 november 2022, zullen indexeerders ondersteund worden met deze functie.
De grammatica van de indexeerfuncties wordt als volgt gewijzigd:
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
;
Partiële indexeerparameters moeten overeenkomen in alle declaraties conform dezelfde regels als overeenkomende signaturen. Attributen samenvoegen wordt uitgevoerd op gedeeltelijke indexeringsparameters.
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;
}
}
Een communitylid heeft een discussie geopend om ondersteuning te vragen voor gedeeltelijke gebeurtenissen. In de LDM-vergadering op 2 november 2022, hebben we besloten om de ondersteuning voor evenementen voorlopig uit te stellen, deels omdat niemand er op dat moment om had gevraagd. We willen deze vraag misschien opnieuw bekijken, omdat dit verzoek nu binnen is gekomen, en het is meer dan een jaar geleden dat we het voor het laatst hebben besproken.
We kunnen ook nog verder gaan met het toestaan van gedeeltelijke declaraties van constructors, operators, velden enzovoort, maar het is onduidelijk of de ontwerplast van deze gerechtvaardigd is, alleen omdat we al gedeeltelijke eigenschappen gebruiken.
C# feature specifications-feedback
C# feature specifications is een open source project. Selecteer een koppeling om feedback te geven: