Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Opmerking
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 relevante 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.
Kampioensprobleem: https://github.com/dotnet/csharplang/issues/9101
Samenvatting
Het toestaan aan gebruikerstypen om het gedrag van samengestelde toewijzingsoperatoren aan te passen op een manier waarop het doel van de toewijzing direct wordt gemodificeerd.
Motivatie
C# biedt ondersteuning voor het overbelasten van operatorimplementaties voor door de gebruiker gedefinieerde typen.
Daarnaast biedt het ondersteuning voor 'samengestelde toewijzingsoperatoren', waarmee de gebruiker code op een vergelijkbare manier als x += y
kan schrijven in plaats van x = x + y
. De taal staat momenteel echter niet toe dat de ontwikkelaar deze samengestelde toewijzingsoperatoren overbelast raakt en hoewel het standaardgedrag het juiste doet, vooral omdat het betrekking heeft op onveranderbare waardetypen, is het niet altijd 'optimaal'.
In het volgende voorbeeld
class C1
{
static void Main()
{
var c1 = new C1();
c1 += 1;
System.Console.Write(c1);
}
public static C1 operator+(C1 x, int y) => new C1();
}
met de huidige taalregels roept samengestelde toewijzingsoperator c1 += 1
door de gebruiker gedefinieerde +
operator aan en wijst vervolgens de retourwaarde toe aan de lokale variabele c1
. Houd er rekening mee dat de implementatie van operatoren een nieuw exemplaar van C1
moet toewijzen en retourneren. Vanuit het perspectief van de consument zou een in-place wijziging van het oorspronkelijke exemplaar van C1
in plaats daarvan net zo goed werken (het wordt niet gebruikt na de toewijzing), met het bijkomende voordeel dat een extra toewijzing wordt vermeden.
Wanneer een programma gebruikmaakt van een samengestelde toewijzingsbewerking, is het meest voorkomende effect dat de oorspronkelijke waarde 'verloren' is en niet meer beschikbaar is voor het programma. Met typen met grote gegevens (zoals BigInteger, Tensors, enzovoort) zijn de kosten voor het produceren van een netto nieuwe bestemming, het herhalen en kopiëren van het geheugen meestal redelijk duur. Een in-place mutatie zou deze kosten in veel gevallen kunnen overslaan, wat aanzienlijke verbeteringen in dergelijke scenario's kan bieden.
Daarom kan het nuttig zijn voor C# om gebruikerstypen toe te staan het gedrag van samengestelde toewijzingsoperators aan te passen en scenario's te optimaliseren die anders moeten worden toegewezen en gekopieerd.
Gedetailleerd ontwerp
Syntaxis
De grammatica bij https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/classes.md#15101-general is als volgt aangepast.
Operators worden gedeclareerd met operator_declarations:
operator_declaration
: attributes? operator_modifier+ operator_declarator operator_body
;
operator_modifier
: 'public'
| 'static'
| 'extern'
| unsafe_modifier // unsafe code support
| 'abstract'
| 'virtual'
| 'sealed'
+ | 'override'
+ | 'new'
+ | 'readonly'
;
operator_declarator
: unary_operator_declarator
| binary_operator_declarator
| conversion_operator_declarator
+ | increment_operator_declarator
+ | compound_assignment_operator_declarator
;
unary_operator_declarator
: type 'operator' overloadable_unary_operator '(' fixed_parameter ')'
;
logical_negation_operator
: '!'
;
overloadable_unary_operator
- : '+' | 'checked'? '-' | logical_negation_operator | '~' | 'checked'? '++' | 'checked'? '--' | 'true' | 'false'
+ : '+' | 'checked'? '-' | logical_negation_operator | '~' | 'true' | 'false'
;
binary_operator_declarator
: type 'operator' overloadable_binary_operator
'(' fixed_parameter ',' fixed_parameter ')'
;
overloadable_binary_operator
: 'checked'? '+' | 'checked'? '-' | 'checked'? '*' | 'checked'? '/' | '%' | '&' | '|' | '^' | '<<'
| right_shift | '==' | '!=' | '>' | '<' | '>=' | '<='
;
conversion_operator_declarator
: 'implicit' 'operator' type '(' fixed_parameter ')'
| 'explicit' 'operator' type '(' fixed_parameter ')'
;
+increment_operator_declarator
+ : type 'operator' overloadable_increment_operator '(' fixed_parameter ')'
+ | 'void' 'operator' overloadable_increment_operator '(' ')'
+ ;
+overloadable_increment_operator
+ : 'checked'? '++' | 'checked'? '--'
+ ;
+compound_assignment_operator_declarator
+ : 'void' 'operator' overloadable_compound_assignment_operator
+ '(' fixed_parameter ')'
+ ;
+overloadable_compound_assignment_operator
+ : 'checked'? '+=' | 'checked'? '-=' | 'checked'? '*=' | 'checked'? '/=' | '%=' | '&=' | '|=' | '^=' | '<<='
+ | right_shift_assignment
+ | unsigned_right_shift_assignment
+ ;
operator_body
: block
| '=>' expression ';'
| ';'
;
Er zijn vijf categorieën overbelaste operators: unaire operators, binaire operators, conversieoperators, incrementele operators, samengestelde toewijzingsoperatoren.
De volgende regels zijn van toepassing op alle operatordeclaraties:
- Een operatordeclaratie omvat
zoweleenpublic
als eenwijzigingsfunctie.static
Operators voor samengestelde toewijzingen en instance-increment kunnen operators verbergen die zijn gedeclareerd in een basisklasse. De volgende alinea is daarom niet meer nauwkeurig en moet dienovereenkomstig worden aangepast, of kan worden verwijderd:
Omdat operatordeclaraties altijd de klasse of struct vereisen waarin de operator wordt gedeclareerd om deel te nemen aan de handtekening van de operator, is het niet mogelijk voor een operator die is gedeclareerd in een afgeleide klasse om een operator te verbergen die is gedeclareerd in een basisklasse.
new
De wijzigingsfunctie is dus nooit vereist en daarom nooit toegestaan in een operatordeclaratie.
Unaire operators
Zie https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/classes.md#15102-unary-operators.
Een operatorverklaring moet een static
modifier bevatten en mag geen override
modifier bevatten.
Het volgende opsommingsteken wordt verwijderd:
- Een unaire
++
of--
operator neemt één parameter van het typeT
ofT?
retourneert hetzelfde type of een type dat ermee is afgeleid.
De volgende alinea wordt aangepast om de ++
- en --
-operatortokens niet meer te vermelden.
De handtekening van een unaire operator bestaat uit het operatortoken (
+
, ,-
!
,~
++
, ,--
oftrue
false
) en het type van de enkele parameter. Het retourtype maakt geen deel uit van de handtekening van een unaire operator en is evenmin de naam van de parameter.
Een voorbeeld in de sectie moet worden aangepast om geen door de gebruiker gedefinieerde incrementele operator te gebruiken.
Binaire operatoren
Zie https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/classes.md#15103-binary-operators.
Een operatorverklaring moet een static
modifier bevatten en mag geen override
modifier bevatten.
Conversieoperators
Een operatorverklaring moet een static
modifier bevatten en mag geen override
modifier bevatten.
Operatoren voor incrementele stappen
De volgende regels zijn van toepassing op declaraties van statische incrementele operatoren, waarbij T
het exemplaartype van de klasse of struct wordt aangegeven die de operatordeclaratie bevat:
- Een operatorverklaring moet een
static
modifier bevatten en mag geenoverride
modifier bevatten. - Een operator neemt één parameter van het type
T
ofT?
retourneert hetzelfde type of een type dat ermee is afgeleid.
De handtekening van een statische incrementele operator bestaat uit de operatortokens ('checked'? ++
, 'checked'? --
) en het type van de enkele parameter.
Het retourtype maakt geen deel uit van de handtekening van een statische incrementele operator en is evenmin de naam van de parameter.
Statische incrementele operators zijn vergelijkbaar met unaire operators.
De volgende regels zijn van toepassing op declaraties van instantie-increment-operatoren:
- Een operatordeclaratie mag geen wijzigingsfunctie bevatten
static
. - Een operator neemt geen parameters.
- Een operator moet een
void
returntype hebben.
In feite is een increment operator voor instantie een methode die void retourneert, geen parameters heeft en een speciale naam heeft in de metadata.
De handtekening van een toenameoperator bestaat uit de operatortokens ('gecontroleerd'? '++' | 'gecontroleerd'? '--').
Een checked operator
verklaring vereist een paarsgewijze verklaring van een regular operator
. Anders treedt er een compilatiefout op.
Zie ook https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/checked-user-defined-operators.md#semantics.
Het doel van de methode is om de waarde van het exemplaar aan te passen aan het resultaat van de aangevraagde incrementele bewerking, wat dat ook betekent in de context van het declaratietype.
Voorbeeld:
class C1
{
public int Value;
public void operator ++()
{
Value++;
}
}
Een increment-operator kan een operator met dezelfde signatuur overschrijven die in een basisklasse is gedeclareerd. Hiervoor kan een override
modifier worden gebruikt.
De volgende "gereserveerde" speciale namen moeten worden toegevoegd aan ECMA-335 ter ondersteuning van exemplaarversies van increment/decrement operators: | Naam | Operator | | -----| -------- | |op_DecrementAssignment| --
| |op_IncrementAssignment| ++
| |op_CheckedDecrementAssignment| gecontroleerd --
| |op_CheckedIncrementAssignment| gecontroleerd ++
|
Operatoren voor samengestelde toewijzing
De volgende regels zijn van toepassing op declaraties van samengestelde toewijzingsoperatoren:
- Een operatordeclaratie mag geen wijzigingsfunctie bevatten
static
. - Een operator neemt één parameter.
- Een operator moet een
void
returntype hebben.
In feite is een operator voor samengestelde toewijzing een ongeldige methode voor het retourneren van exemplaren die één parameter gebruikt en een speciale naam heeft in metagegevens.
De handtekening van een samengestelde toewijzingsoperator bestaat uit de operatortokens ('ingeschakeld'? '+=', 'ingeschakeld'? '-=', 'ingeschakeld'? '*=', 'ingeschakeld'? '/=', '%=', '&=', '|=', '^=', '
Een checked operator
verklaring vereist een paarsgewijze verklaring van een regular operator
. Anders treedt er een compilatiefout op.
Zie ook https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/checked-user-defined-operators.md#semantics.
Het doel van de methode is om de waarde van de instantie af te stemmen op het resultaat van <instance> <binary operator token> parameter
.
Voorbeeld:
class C1
{
public int Value;
public void operator +=(int x)
{
Value+=x;
}
}
Een operator voor samengestelde toewijzing kan een operator met dezelfde handtekening die is gedeclareerd in een basisklasse overschrijven. Hiervoor kan een override
wijzigingsfunctie worden gebruikt.
ECMA-335 heeft de volgende speciale namen al gereserveerd voor door de gebruiker gedefinieerde incrementele operators: | Naam | Operator | | -----| -------- | |op_AdditionAssignment|' +=' | |op_SubtractionAssignment|' -=' | |op_MultiplicationAssignment|' *=' | |op_DivisionAssignment|' /=' | |op_ModulusAssignment|'%=' | |op_BitwiseAndAssignment|' &=' | |op_BitwiseOrAssignment|'|=' | |op_ExclusiveOrAssignment|' ^=' | |op_LeftShiftAssignment|'<<='| |op_RightShiftAssignment| right_shift_assignment| |op_UnsignedRightShiftAssignment|unsigned_right_shift_assignment|
Het geeft echter aan dat CLS-naleving vereist dat de operatormethoden niet-ongeldige statische methoden zijn met twee parameters, d.w. komt overeen met wat binaire C#-operators zijn. We moeten overwegen om de CLS-nalevingsvereisten te versoepelen, zodat de operators retournerende exemplaarmethoden met één parameter ongeldig kunnen maken.
De volgende namen moeten worden toegevoegd ter ondersteuning van gecontroleerde versies van de operators: | Naam | Operator | | -----| -------- | |op_CheckedAdditionAssignment| ingeschakeld +=| |op_CheckedSubtractionAssignment| ingeschakeld -=| |op_CheckedMultiplicationAssignment | ingeschakeld *=| |op_CheckedDivisionAssignment| ingeschakeld '/=' |
Operatoren voor prefixverhoging en -verlaging
Als x
in «op» x
is geclassificeerd als een variabele en er een nieuwe taalversie wordt getarget, wordt de prioriteit als volgt gegeven aan instantie-incrementele operators.
Eerst wordt geprobeerd de bewerking te verwerken door de overload-resolutie van de operator voor het verhogen van instanties toe te passen. Als het proces geen resultaat en evenmin een fout oplevert, wordt de bewerking uitgevoerd door de resolutie van de overbelasting van een unaire operator toe te passen zoals dat momenteel is bepaald in https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#1296-prefix-increment-and-decrement-operators.
Anders wordt een bewerking «op»x
als volgt geëvalueerd.
Als het type van x
bekend is als een verwijzingstype, wordt x
geëvalueerd om een exemplaar x₀
op te halen, wordt de operatormethode op dat exemplaar aangeroepen en wordt x₀
geretourneerd als het resultaat van de bewerking.
Als x₀
null
is, zal de aanroep van de operatormethode een NullReferenceException genereren.
Voorbeeld:
var a = ++(new C()); // error: not a variable
var b = ++a; // var temp = a; temp.op_Increment(); b = temp;
++b; // b.op_Increment();
var d = ++C.P1; // error: setter is missing
++C.P1; // error: setter is missing
var e = ++C.P2; // var temp = C.op_Increment(C.get_P2()); C.set_P2(temp); e = temp;
++C.P2; // var temp = C.op_Increment(C.get_P2()); C.set_P2(temp);
class C
{
public static C P1 { get; } = new C();
public static C P2 { get; set; } = new C();
public static C operator ++(C x) => ...;
public void operator ++() => ...;
}
Als het x
type niet bekend is als verwijzingstype:
- Als het resultaat van verhoging wordt gebruikt, wordt
x
geëvalueerd om een exemplaarx₀
op te halen, wordt de operatormethode op dat exemplaar aangeroepen, wordtx₀
toegewezen aanx
enx₀
wordt geretourneerd als resultaat van de samengestelde toewijzing. - Anders wordt de operator-methode uitgevoerd op
x
.
Houd er rekening mee dat bijwerkingen x
slechts eenmaal in het proces worden geëvalueerd.
Voorbeeld:
var a = ++(new S()); // error: not a variable
var b = ++S.P2; // var temp = S.op_Increment(S.get_P2()); S.set_P2(temp); b = temp;
++S.P2; // var temp = S.op_Increment(S.get_P2()); S.set_P2(temp);
++b; // b.op_Increment();
var d = ++S.P1; // error: set is missing
++S.P1; // error: set is missing
var e = ++b; // var temp = b; temp.op_Increment(); e = (b = temp);
struct S
{
public static S P1 { get; } = new S();
public static S P2 { get; set; } = new S();
public static S operator ++(S x) => ...;
public void operator ++() => ...;
}
Postfix operatoren voor incrementeren en decrementeren
Als het resultaat van de bewerking wordt gebruikt of x
in x «op»
niet als een variabele is geclassificeerd of een oude taalversie wordt gericht, wordt de bewerking verwerkt door de oplossing voor overbelasting van een unaire operator toe te passen zoals https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12816-postfix-increment-and-decrement-operators dat momenteel specificeert.
De reden waarom we niet eens proberen instance-increment operatoren te gebruiken wanneer het resultaat wordt gebruikt, is het feit dat, als we te maken hebben met een verwijzingstype, het niet mogelijk is om de waarde van x
te produceren vóór de bewerking als deze in-place is gewijzigd.
Als we te maken hebben met een waardetype, moeten we toch kopieën maken, enzovoort.
De prioriteit wordt als volgt gegeven aan de instantie-incrementoperatoren.
Eerst wordt geprobeerd de bewerking te verwerken door de overload-resolutie van de operator voor het verhogen van instanties toe te passen. Als het proces geen resultaat en evenmin een fout oplevert, wordt de bewerking uitgevoerd door de resolutie van de overbelasting van een unaire operator toe te passen zoals dat momenteel is bepaald in https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12816-postfix-increment-and-decrement-operators.
Anders wordt een bewerking x«op»
als volgt geëvalueerd.
Als het type van x
bekend is als een verwijzingstype, wordt de operatormethode aangeroepen op x
.
Als x
null
is, zal de aanroep van de operatormethode een NullReferenceException genereren.
Voorbeeld:
var a = (new C())++; // error: not a variable
var b = new C();
var c = b++; // var temp = b; b = C.op_Increment(temp); c = temp;
b++; // b.op_Increment();
var d = C.P1++; // error: missing setter
C.P1++; // error: missing setter
var e = C.P2++; // var temp = C.get_P2(); C.set_P2(C.op_Increment(temp)); e = temp;
C.P2++; // var temp = C.get_P2(); C.set_P2(C.op_Increment(temp));
class C
{
public static C P1 { get; } = new C();
public static C P2 { get; set; } = new C();
public static C operator ++(C x) => ...;
public void operator ++() => ...;
}
Als het type x
niet bekend is als een referentietype, wordt de operatormethode aangeroepen op x
.
Voorbeeld:
var a = (new S())++; // error: not a variable
var b = S.P2++; // var temp = S.get_P2(); S.set_P2(S.op_Increment(temp)); b = temp;
S.P2++; // var temp = S.get_P2(); S.set_P2(S.op_Increment(temp));
b++; // b.op_Increment();
var d = S.P1++; // error: set is missing
S.P1++; // error: missing setter
var e = b++; // var temp = b; b = S.op_Increment(temp); e = temp;
struct S
{
public static S P1 { get; } = new S();
public static S P2 { get; set; } = new S();
public static S operator ++(S x) => ...;
public void operator ++() => ...;
}
Overbelastingsresolutie van de operator voor exemplaarincrementele opdrachten
Een bewerking van het formulier «op» x
of x «op»
, waarbij «op» een overlaadbare instantie-incrementoperator is en x
een expressie van het type X
is, wordt als volgt verwerkt:
- De set door de gebruiker gedefinieerde kandidaatoperators die door
X
worden opgegeven voor de bewerkingoperator «op»(x)
, wordt bepaald met behulp van de regels voor kandidaatexemplaar-incrementele operatoren. - Als de set door de gebruiker gedefinieerde kandidaatoperators niet leeg is, wordt dit de set kandidaatoperators voor de bewerking. Anders levert de overbelastingsresolutie geen resultaat op.
- De regels voor overbelastingsresolutie worden toegepast op de set kandidaat-operators om de beste operator te selecteren en deze operator wordt het resultaat van het overbelastingsoplossingsproces. Als overbelastingsresolutie niet één beste operator selecteert, treedt er een bindingstijdfout op.
Operatoren voor incrementele stappen van kandidaat-exemplaar
Gezien een type T
en een bewerking «op»
, waarbij «op»
een overloadbare instance-incrementoperator is, wordt de door de gebruiker gedefinieerde set van kandidaatoperators T
als volgt bepaald.
- In
unchecked
evaluatiecontext is het een groep operators die worden geproduceerd door het lidopzoekproces wanneer alleen instantie-operatorsoperator «op»()
werden beschouwd als overeenkomend met de specifieke naamN
. - In
checked
evaluatiecontext is het een groep operators die door het lid opzoeken proces wordt geproduceerd wanneer alleen instantieoperator «op»()
- enoperator checked «op»()
-operators als overeenkomend met de doelnaamN
worden beschouwd. Deoperator «op»()
operators die declaraties hebben die onderling overeenkomenoperator checked «op»()
worden uitgesloten van de groep.
Samengestelde toewijzing
De alinea aan het begin die gaat over dynamic
is nog steeds van toepassing.
Anders, als x
in x «op»= y
als een variabele wordt ingedeeld en een nieuwe taalversie is gericht, dan wordt de prioriteit gegeven aan samengestelde toewijzingsoperators zoals volgt.
Eerst wordt geprobeerd een bewerking van het formulier x «op»= y
te verwerken door een overbelastingsoplossing van de operator voor samengestelde toewijzingen toe te passen.
Als het proces geen resultaat en geen fout oplevert, wordt de bewerking verwerkt door een overbelastingsresolutie van een binaire operator toe te passen, zoals momenteel door https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12214-compound-assignment wordt gespecificeerd.
Anders wordt de bewerking als volgt geëvalueerd.
Als bekend is dat type x
een referentietype is, wordt x
geëvalueerd om een instantie x₀
te verkrijgen; de operatormethode wordt op die instantie aangeroepen met y
als argument, en x₀
wordt geretourneerd als het resultaat van de samengestelde toewijzing.
Als x₀
null
is, zal de aanroep van de operatormethode een NullReferenceException genereren.
Voorbeeld:
var a = (new C())+=10; // error: not a variable
var b = a += 100; // var temp = a; temp.op_AdditionAssignment(100); b = temp;
var c = b + 1000; // c = C.op_Addition(b, 1000)
c += 5; // c.op_AdditionAssignment(5);
var d = C.P1 += 11; // error: setter is missing
var e = C.P2 += 12; // var temp = C.op_Addition(C.get_P2(), 12); C.set_P2(temp); e = temp;
C.P2 += 13; // var temp = C.op_Addition(C.get_P2(), 13); C.set_P2(temp);
class C
{
public static C P1 { get; } = new C();
public static C P2 { get; set; } = new C();
// op_Addition
public static C operator +(C x, int y) => ...;
// op_AdditionAssignment
public void operator +=(int y) => ...;
}
Als het x
type niet bekend is als verwijzingstype:
- Als het resultaat van samengestelde toewijzing wordt gebruikt, wordt het
x
geëvalueerd om een exemplaarx₀
op te halen, wordt de operatormethode op dat exemplaar aangeroepen alsy
argument,x₀
toegewezen aanx
enx₀
geretourneerd als gevolg van de samengestelde toewijzing. - Anders wordt de operatormethode op
x
aangeroepen mety
als argument.
Houd er rekening mee dat bijwerkingen x
slechts eenmaal in het proces worden geëvalueerd.
Voorbeeld:
var a = (new S())+=10; // error: not a variable
var b = S.P2 += 100; // var temp = S.op_Addition(S.get_P2(), 100); S.set_P2(temp); b = temp;
S.P2 += 100; // var temp = S.op_Addition(S.get_P2(), 100); S.set_P2(temp);
var c = b + 1000; // c = S.op_Addition(b, 1000)
c += 5; // c.op_AdditionAssignment(5);
var d = S.P1 += 11; // error: setter is missing
var e = c += 12; // var temp = c; temp.op_AdditionAssignment(12); e = (c = temp);
struct S
{
public static S P1 { get; } = new S();
public static S P2 { get; set; } = new S();
// op_Addition
public static S operator +(S x, int y) => ...;
// op_AdditionAssignment
public void operator +=(int y) => ...;
}
Oplossing voor overbelasting van samengestelde toewijzingsoperator
Een bewerking van het formulier x «op»= y
, waarbij «op»=
een overbelastingsbare samengestelde toewijzingsoperator is, x
is een expressie van het type X
wordt als volgt verwerkt:
- De set van door de gebruiker gedefinieerde kandidaatoperators die door
X
zijn opgegeven voor de bewerkingoperator «op»=(y)
, wordt bepaald met behulp van de regels van kandidaat samengestelde toewijzingsoperatoren. - Als ten minste één door de gebruiker gedefinieerde kandidaatoperator in de set van toepassing is op de lijst
(y)
met argumenten, wordt dit de set kandidaatoperators voor de bewerking. Anders levert de overbelastingsresolutie geen resultaat op. - De regels voor overbelastingsoplossing worden toegepast op de set kandidaatoperators om de beste operator te selecteren met betrekking tot de lijst
(y)
met argumenten en deze operator wordt het resultaat van het overbelastingsoplossingsproces. Als overbelastingsresolutie niet één beste operator selecteert, treedt er een bindingstijdfout op.
Operatoren voor gecombineerde toewijzing van kandidaat-operatoren
Gezien een type T
en een bewerking «op»=
, waarbij «op»=
een overbelastbare samengestelde toewijzingsoperator is, wordt de set van door de gebruiker gedefinieerde kandidaatoperatoren geleverd door T
als volgt bepaald:
- In
unchecked
evaluatiecontext is het een groep operators die worden geproduceerd door het lidopzoekproces wanneer alleen instantie-operatorsoperator «op»=(Y)
werden beschouwd als overeenkomend met de specifieke naamN
. - In
checked
evaluatiecontext is het een groep operators die door het lid opzoeken proces wordt geproduceerd wanneer alleen instantieoperator «op»=(Y)
- enoperator checked «op»=(Y)
-operators als overeenkomend met de doelnaamN
worden beschouwd. Deoperator «op»=(Y)
operators die declaraties hebben die onderling overeenkomenoperator checked «op»=(Y)
worden uitgesloten van de groep.
Open vragen
[Opgelost] Moet readonly
wijziging worden toegestaan in structuren?
Het lijkt erop dat er geen voordeel is om een methode te markeren met readonly
wanneer het hele doel van de methode is om het exemplaar te wijzigen.
Conclusie: We zullen modifiers toestaan readonly
, maar we zullen de doelvereisten op dit moment niet versoepelen.
[Opgelost] Moet schaduw worden toegestaan?
Als een afgeleide klasse een 'samengestelde toewijzing'-operator of 'instantie-increment'-operator met dezelfde signatuur als een in de basis declareert, moeten we een override
modifier vereisen?
Conclusie: Schaduwen worden toegestaan met dezelfde regels als methoden.
[Opgelost] Moeten we consistentie verzekeren tussen de gedeclareerde +=
en +
-operators?
Tijdens LDM-2025-02-12 werd een probleem gemeld over auteurs die per ongeluk hun gebruikers pushen naar vreemde scenario's waarbij een +=
mogelijk werkt, maar +
niet (of omgekeerd), omdat een formulier extra operators dan de andere declareert.
Conclusie: Er worden geen controles uitgevoerd voor consistentie tussen verschillende vormen van operators.
Alternatieven
Statische methoden blijven gebruiken
We kunnen overwegen om statische operatormethoden te gebruiken waarbij het exemplaar dat moet worden gedempt, wordt doorgegeven als de eerste parameter. In het geval van een waardetype moet deze parameter een ref
parameter zijn.
Anders kan de methode de doelvariabele niet muteren. In het geval van een klassetype mag die parameter tegelijkertijd geen parameter zijn ref
. Omdat in het geval van een klasse de doorgegeven instantie moet worden gemuteerd, niet de locatie waar de instantie is opgeslagen. Wanneer een operator echter in een interface wordt gedeclareerd, is het vaak niet bekend of de interface alleen door klassen of alleen door structuren wordt geïmplementeerd. Daarom is het niet duidelijk of de eerste parameter een ref
parameter moet zijn.
Ontwerpbijeenkomsten
C# feature specifications