Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Notatka
Ten artykuł jest specyfikacją funkcji. Specyfikacja służy jako dokument projektowy dla funkcji. Zawiera proponowane zmiany specyfikacji wraz z informacjami wymaganymi podczas projektowania i opracowywania funkcji. Te artykuły są publikowane do momentu sfinalizowania proponowanych zmian specyfikacji i włączenia ich do obecnej specyfikacji ECMA.
Mogą wystąpić pewne rozbieżności między specyfikacją funkcji a ukończoną implementacją. Te różnice są uchwycone w odpowiednich notatkach ze spotkania projektowania języka (LDM) .
Więcej informacji na temat procesu wdrażania specyfikacji funkcji można znaleźć w standardzie języka C# w artykule dotyczącym specyfikacji .
Problem z czempionem: https://github.com/dotnet/csharplang/issues/6420
Gramatyka
property_declaration gramatyka (§14.7.1) została zaktualizowana w następujący sposób:
property_declaration
- : attributes? property_modifier* type member_name property_body
+ : attributes? property_modifier* 'partial'? type member_name property_body
;
Uwagi: To nieco przypomina sposób, w jaki method_header(§15.6.1) i class_declaration(§15.2.1) są określone. (Należy pamiętać, że problem nr 946 proponuje złagodzenie wymagania porządkowania i prawdopodobnie będzie miało zastosowanie do wszystkich deklaracji, które zezwalają na modyfikator partial. Zamierzamy określić takie złagodzenie kolejności w najbliższej przyszłości i zaimplementować go w tej samej wersji, że ta funkcja jest implementowana.
Definiowanie i implementowanie deklaracji
Gdy deklaracja właściwości zawiera częściowy modyfikator, ta właściwość jest uważana za właściwość częściową . Właściwości częściowe mogą być deklarowane tylko jako członkowie typów częściowych.
Mówi się, że częściowa deklaracja właściwości jest deklaracją definiującą deklarację, gdy wszystkie jej akcesoria mają ciała średników i nie ma modyfikatora extern. W przeciwnym razie jest to deklaracja implementująca .
partial class C
{
// Defining declaration
public partial string Prop { get; set; }
// Implementing declaration
public partial string Prop { get => field; set => field = value; }
}
Ponieważ zarezerwowano formę składniową z ciałami akcesorów przy użyciu średnika dla definiującej deklaracji, właściwość częściowa nie może być automatycznie zaimplementowana. Dlatego dostosujemy automatycznie zaimplementowane właściwości (§15.7.4) w następujący sposób:
Automatycznie zaimplementowana właściwość (lub właściwość automatyczna w skrócie) jest nieabstrakcyjną, nieextern, nie-częściową, nieodnoszącą się do wartości ref właściwością z ciałami akcesorów składającymi się tylko z średników.
uwagi. Kompilator jest przydatny, aby móc przyjrzeć się pojedynczej deklaracji w izolacji i wiedzieć, czy jest to deklaracja definiująca, czy implementowana. W związku z tym nie chcemy zezwalać na automatyczne właściwości poprzez użycie dwóch identycznych deklaracji właściwości partial, na przykład. Nie uważamy, że przypadki użycia tej funkcji obejmują zaimplementowanie właściwości częściowej z właściwością automatyczną, ale w przypadkach, gdy wymagana jest implementacja trywialna, uważamy, że słowo kluczowe field sprawia, że rzeczy są wystarczająco proste.
Właściwość częściowa musi mieć jedną definiującą deklarację i jedną implementującą deklarację .
uwagi. Nie uważamy również, że warto zezwolić na podzielenie deklaracji na więcej niż dwie części, aby umożliwić wdrożenie różnych metod dostępu w różnych miejscach, na przykład. W związku z tym po prostu naśladujemy schemat ustalony przez częściowe metody.
Tylko zdefiniowana deklaracja częściowej właściwości uczestniczy w wyszukiwaniu, podobnie jak w sposobie, w jaki tylko deklaracja definiująca metodę częściową uczestniczy w rozpoznawaniu przeciążeń.
uwagi. W kompilatorze spodziewalibyśmy się, że na liście członków pojawia się tylko symbol deklaracji definiującej, a do symbolu części implementacyjnej można uzyskać dostęp za pośrednictwem symbolu definiującego. Jednak niektóre funkcje, takie jak analiza dopuszczana do wartości null, mogą zobaczyć za pośrednictwem do deklaracji implementowania w celu zapewnienia bardziej przydatnego zachowania.
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.
{
}
}
Właściwość częściowa nie może mieć modyfikatora abstract.
Właściwość częściowa nie może jawnie implementować właściwości interfejsu.
Scalanie atrybutów
Podobnie jak w przypadku metod częściowych, atrybuty w wynikowej właściwości są połączone z atrybutami części w nieokreślonej kolejności, a duplikaty nie są usuwane.
Atrybuty informacji o dzwoniącym
Dostosowujemy następujący język ze standardu :
Jest błędem mieć ten sam atrybut caller-info dla parametru zarówno w części definiującej, jak i implementującej częściowej deklaracji metody
członka. Stosowane są tylko atrybuty caller-info w części definiującej, natomiast atrybuty caller-info występujące tylko w części implementowania są ignorowane.
- Opisany błąd wypada z definicji tych atrybutów, które nie mają
AllowMultiple = true. Użycie ich wiele razy, w tym w przypadku deklaracji częściowych, powoduje wystąpienie błędu. - Gdy atrybuty caller-info są stosowane do parametru w części implementacji metody częściowej, kompilator Roslyn zgłasza ostrzeżenie. Zostanie również wyświetlone ostrzeżenie dotyczące tego samego scenariusza we właściwości częściowej.
Pasujące podpisy
Spotkanie LDM w dniu 14 września 2020 r. zdefiniowało zestaw „surowych” wymagań dotyczących dopasowywania podpisów metod częściowych, które zostały wprowadzone w fali ostrzeżeń. Właściwości częściowe mają podobne wymagania co do metod częściowych w kontekście dopasowywania podpisów w miarę możliwości, z tym że wszelkie informacje o niezgodnościach są domyślnie zgłaszane i nie są ukrywane za falą ostrzeżeń.
Wymagania dotyczące dopasowywania podpisów obejmują:
- Różnice w typach i typach referencyjnych między częściowymi deklaracjami właściwości, które mają znaczenie dla wyniku działania programu, powodują błąd w czasie kompilacji.
- Różnice w nazwach elementów krotki w częściowych deklaracjach właściwości powodują błąd kompilacji, podobnie jak w przypadku metod częściowych.
- Deklaracje właściwości i ich deklaracje dostępu muszą mieć te same modyfikatory, choć modyfikatory mogą występować w innej kolejności.
- Wyjątek: nie ma to zastosowania do modyfikatora
extern, który może występować tylko w deklaracji implementowania.
- Wyjątek: nie ma to zastosowania do modyfikatora
- Wszystkie inne różnice składniowe w podpisach częściowych deklaracji właściwości powodują ostrzeżenie w czasie kompilacji z następującymi wyjątkami:
- Listy atrybutów w deklaracjach właściwości częściowych lub w ich obrębie nie muszą być zgodne. Zamiast tego scalanie atrybutów w odpowiednich pozycjach jest wykonywane zgodnie z Scalanie atrybutów.
- Różnice kontekstu dopuszczające wartość null nie powodują ostrzeżeń. Innymi słowy, różnica polegająca na tym, że jeden z typów jest nieświadomy wartości null, a drugi typ jest albo z adnotacją nullable, lub nieobsługującym wartości null, nie powoduje żadnych ostrzeżeń.
- Domyślne wartości parametrów nie muszą być zgodne. Ostrzeżenie jest zgłaszane, gdy implementacja indeksatora częściowego ma domyślne wartości parametrów. Jest to podobne do istniejącego ostrzeżenia, które występuje, gdy część implementacji metody częściowej ma domyślne wartości parametrów.
- Ostrzeżenie występuje, gdy nazwy parametrów różnią się w zależności od definiowania i implementowania deklaracji. Nazwy parametrów z części definicji są używane w miejscach użycia i podczas emitowania.
- Różnice dotyczące wartości null, które nie obejmują ignorowania wartości null, powodują ostrzeżenia. Podczas analizowania treści akcesora używany jest podpis części implementacji. Podpis definicji jest używany podczas analizy miejsc użycia i w procesie emitowania. Jest to zgodne z metodami częściowymi.
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
}
Komentarze do dokumentacji
Chcemy, aby zachowanie komentarzy dokumentacyjnych dotyczących właściwości częściowych było spójne z tym, co dostarczono dla metod częściowych. To zachowanie zostało szczegółowo opisane w https://github.com/dotnet/csharplang/issues/5193.
Można dołączać komentarze dokumentacyjne do definicji lub implementacji częściowej właściwości. (Zwróć uwagę, że komentarze do dokumentu nie są obsługiwane w przypadku metod dostępu do właściwości).
Gdy komentarze dokumentacyjne są obecne tylko w jednej z części właściwości, są one używane normalnie (widoczne za pośrednictwem ISymbol.GetDocumentationCommentXml(), zapisywane w pliku XML dokumentacji itp.).
Gdy komentarze doc są obecne w obu częściach, wszystkie komentarze dokumentu w części definicji są porzucane, a używane są tylko komentarze dokumentu dotyczące części implementacji.
Na przykład następujący 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 { } }
}
Wyniki w następującym pliku dokumentacji 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>
Gdy nazwy parametrów różnią się w deklaracjach częściowych, elementy <paramref> używają nazw parametrów z deklaracji, która jest powiązana z komentarzem dokumentacji w kodzie źródłowym. Na przykład paramref w komentarzu doc umieszczonym w deklaracji implementowania odnosi się do symboli parametrów w deklaracji implementowania przy użyciu ich nazw parametrów. Jest to zgodne z metodami częściowymi.
/// <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.
}
Wyniki w następującym pliku dokumentacji 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>
Może to być mylące, ponieważ podpis metadanych będzie używać nazw parametrów ze części definicji. Zaleca się, aby nazwy parametrów były zgodne między częściami, aby uniknąć tego zamieszania.
Indeksatorzy
Na spotkaniu LDM w dniu 2 listopada 2022 r.indeksatorzy będą wspierani tą funkcją.
Gramatyka indeksatorów jest modyfikowana w następujący sposób:
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
;
Parametry indeksatora częściowego muszą być zgodne między deklaracjami zgodnie z tymi samymi zasadami co zgodność sygnatur. Scalanie atrybutów jest wykonywane w poprzek częściowych parametrów indeksatora.
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;
}
}
Otwarte problemy
Inne rodzaje członków
Członek społeczności otworzył dyskusję, aby poprosić o wsparcie dla częściowych wydarzeń . W spotkaniu LDM w dniu 2 listopada 2022 r.postanowiliśmy odłożyć wsparcie dla wydarzeń, częściowo dlatego, że nikt w tamtym czasie się go nie domagał. Możemy chcieć ponownie zapoznać się z tym pytaniem, ponieważ wniosek ten przyszedł i minęło ponad rok od czasu ostatniej dyskusji.
Moglibyśmy pójść jeszcze dalej, pozwalając na częściowe deklaracje konstruktorów, operatorów, pól itd., ale nie jest jasne, czy obciążenie projektowe tych elementów jest uzasadnione, tylko dlatego, że już stosujemy częściowe właściwości.
C# feature specifications