Sdílet prostřednictvím


Uživatelem definované operátory složeného přiřazení

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 ze schůzky jazykového návrhu (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/9101

Shrnutí

Umožňuje uživatelům přizpůsobit chování operátorů složeného přiřazení způsobem, který cíl přiřazení upraví na místě.

Motivace

Jazyk C# poskytuje podporu pro implementace operátoru přetížení vývojáře pro uživatelem definovaný typ. Kromě toho poskytuje podporu pro "složené operátory přiřazení", které uživateli umožňují psát kód podobně jako x += yx = x + y. Jazyk však v současné době neumožňuje vývojáři přetížit tyto operátory složeného přiřazení a zatímco výchozí chování dělá správnou věc, zejména pokud se týká neměnných hodnotových typů, není vždy "optimální".

Vzhledem k následujícímu příkladu

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

pomocí aktuálních pravidel jazyka operátor c1 += 1 složeného přiřazení vyvolá uživatelem definovaný + operátor a pak přiřadí jeho návratovou hodnotu k místní proměnné c1. Všimněte si, že implementace operátoru musí přidělit a vrátit novou instanci C1, zatímco z pohledu příjemce by místní změna na původní instanci C1 místo toho fungovala stejně dobře (není použita po přiřazení), s další výhodou, že se vyhnout nadbytečnému přidělení.

Když program využívá operaci složeného přiřazení, nejběžnějším účinkem je, že původní hodnota je "ztracena" a už není k dispozici pro program. U typů s velkými objemy dat (například BigInteger, Tensors atd.) jsou náklady na vytvoření čisté nové cíle, iterace a kopírování paměti poměrně nákladné. Místní varianta by umožnila vynechat tyto výdaje v mnoha případech, což může přinést významná vylepšení takových scénářů.

Proto může být přínosné pro jazyk C# umožnit uživatelům přizpůsobit chování operátorů složeného přiřazení a optimalizovat scénáře, které by jinak potřebovaly přidělit a kopírovat.

Podrobný návrh

Syntaxe

https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/classes.md#15101-general Gramatika je upravena následujícím způsobem.

Operátory jsou deklarovány pomocí 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 ';'
    | ';'
    ;

Existuje pět kategorií přetížitelných operátorů: unární operátory, binární operátory, operátory převodu, operátory přírůstku, složené operátory přiřazení.

Následující pravidla platí pro všechny deklarace operátorů:

  • Prohlášení operátoru publiczahrnuje static modifikátor, tak i modifikátor.

Složené operátory přiřazení a inkrementace instancí mohou skrýt operátory deklarované v základní třídě. Proto následující odstavec již není přesný a měl by být odpovídajícím způsobem upraven nebo lze jej odebrat:

Vzhledem k tomu, že deklarace operátorů vždy vyžadují třídu nebo strukturu, ve které je operátor deklarován pro účast v podpisu operátoru, není možné, aby operátor deklarovaný v odvozené třídě skryl operátor deklarovaný v základní třídě. new Modifikátor se tedy nikdy nevyžaduje, a proto není nikdy povolen v deklaraci operátoru.

Unární operátory

Viz https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/classes.md#15102-unary-operators.

Prohlášení operátoru static musí obsahovat modifikátor a nesmí obsahovat override modifikátor.

Následující odrážka se odebere:

  • Unární ++ nebo -- operátor přijme jeden parametr typu T nebo T? vrátí stejný typ nebo typ odvozený z něj.

Následující odstavec se upraví tak, aby již nezmínil tokeny operátoru a ++ nezmínil--:

Podpis unárního operátoru se skládá z tokenu operátoru (+, -!, ~, ++, --, , true, nebo false) a typu jednoho parametru. Návratový typ není součástí podpisu unárního operátoru ani není název parametru.

Příklad v oddílu by se měl upravit tak, aby nepoužíval uživatelem definovaný operátor přírůstku.

Binární operátory

Viz https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/classes.md#15103-binary-operators.

Prohlášení operátoru static musí obsahovat modifikátor a nesmí obsahovat override modifikátor.

Operátory převodu

Viz https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/classes.md#15104-conversion-operators.

Prohlášení operátoru static musí obsahovat modifikátor a nesmí obsahovat override modifikátor.

Operátory přírůstku

Následující pravidla platí pro deklarace statického operátoru přírůstku, kde T označuje typ instance třídy nebo struktury, která obsahuje deklaraci operátoru:

  • Prohlášení operátoru static musí obsahovat modifikátor a nesmí obsahovat override modifikátor.
  • Provozovatel převezme jeden parametr typu T nebo T? vrátí stejný typ nebo typ odvozený z něj.

Podpis statického operátoru přírůstku se skládá z tokenů operátoru ('checked'? ++, 'checked'? --) a typu jednoho parametru. Návratový typ není součástí podpisu statického operátoru přírůstku ani název parametru.

Statické operátory přírůstku jsou velmi podobné unárním operátorům.

Následující pravidla platí pro deklarace operátoru přírůstku instance:

  • Deklarace operátoru static nesmí obsahovat modifikátor.
  • Provozovatel nepřebírají žádné parametry.
  • Operátor musí mít void návratový typ.

Operátor inkrementace instance je void návratové metody instance, která nemá žádné parametry a má speciální název v metadatech.

Podpis operátoru přírůstku instance se skládá z tokenů operátoru ("zaškrtnuto"? '++' | "Zaškrtnuto"? '--').

Deklarace checked operator vyžaduje párově moudrou regular operatordeklaraci . V opačném případě dojde k chybě kompilace. Viz také https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/checked-user-defined-operators.md#semantics.

Účelem metody je upravit hodnotu instance na výsledek požadované operace přírůstku, ať už to znamená v kontextu deklarujícího typu.

Příklad:

class C1
{
    public int Value;

    public void operator ++()
    {
        Value++;
    }
}

Operátor inkrementace instance může přepsat operátor se stejným podpisem deklarovaným v základní třídě, override modifikátor lze použít pro tento účel.

Do ECMA-335 by se měly přidat následující speciální názvy "reserved", aby podporovaly verze instancí operátorů přírůstku/dekrementace: | Název | Operátor | | -----| -------- | |op_DecrementAssignment| -- | |op_IncrementAssignment| ++ | |op_CheckedDecrementAssignment| zaškrtnuto -- | |op_CheckedIncrementAssignment| zaškrtnuto ++ |

Operátory složeného přiřazení

Následující pravidla platí pro deklarace operátoru složeného přiřazení:

  • Deklarace operátoru static nesmí obsahovat modifikátor.
  • Operátor převezme jeden parametr.
  • Operátor musí mít void návratový typ.

Operátor složeného přiřazení je void vracející metodu instance, která přebírá jeden parametr a má zvláštní název v metadatech.

Podpis operátoru složeného přiřazení se skládá z tokenů operátoru ("zaškrtnuto"? "+=", "zaškrtnuto"? '-=', 'zaškrtnuto'? '*=', 'checked'? '/=', '%=', '&=', '|=', '^=', '<<=', right_shift_assignment, unsigned_right_shift_assignment) a typ jednoho parametru. Název parametru není součástí podpisu operátoru složeného přiřazení.

Deklarace checked operator vyžaduje párově moudrou regular operatordeklaraci . V opačném případě dojde k chybě kompilace. Viz také https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/checked-user-defined-operators.md#semantics.

Účelem metody je upravit hodnotu instance na výsledek <instance> <binary operator token> parameter.

Příklad:

class C1
{
    public int Value;

    public void operator +=(int x)
    {
        Value+=x;
    }
}

Operátor složeného přiřazení může přepsat operátor se stejným podpisem deklarovaným v základní třídě, override modifikátor lze použít pro tento účel.

ECMA-335 již "rezervováno" následující speciální názvy pro uživatelem definované operátory přírůstku: | Název | Operátor | | -----| -------- | |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|

Uvádí však, že dodržování předpisů CLS vyžaduje, aby metody operátoru byly statické metody bez void se dvěma parametry, tj. odpovídá tomu, co jsou binární operátory jazyka C#. Měli bychom zvážit uvolnění požadavků na dodržování předpisů CLS, aby operátory mohly být neplatné návratové metody instance s jedním parametrem.

Pro podporu kontrolovaných verzí operátorů by se měly přidat následující názvy: | Název | Operátor | | -----| -------- | |op_CheckedAdditionAssignment| zaškrtnuto '+=' | |op_CheckedSubtractionAssignment| zaškrtnuto '-=' | |op_CheckedMultiplicationAssignment| zaškrtnuto '*=' | |op_CheckedDivisionAssignment| zaškrtnuto '/=' |

Operátory inkrementace a dekrementace předpony

Viz https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#1296-prefix-increment-and-decrement-operators.

Pokud x je in «op» x klasifikovaná jako proměnná a cílí na novou jazykovou verzi, pak se priorita přiřadí operátorům inkrementace instancí následujícím způsobem.

Nejprve je proveden pokus o zpracování operace použitím operátoru zvýšení instance přetížení. Pokud proces nevygeneruje žádný výsledek a žádná chyba, operace se zpracuje použitím rozlišení přetížení unárního operátoru, jak https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#1296-prefix-increment-and-decrement-operators je aktuálně uvedeno.

V opačném případě se operace «op»x vyhodnotí následujícím způsobem.

Pokud je známo, že typ x odkazu, je vyhodnocen získat x instanci x₀, operátor metoda je vyvolána na této instanci a x₀ je vrácena v důsledku operace. Pokud x₀ je null, vyvolání metody operátoru vyvolá nullReferenceException.

Například:

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 ++() => ...;
}

Pokud typ x není znám jako odkazový typ:

  • Pokud se použije výsledek přírůstku, x vyhodnotí se získat instanci x₀, operátor metoda je vyvolána na této instanci, x₀ je přiřazena x a x₀ je vrácena v důsledku složeného přiřazení.
  • V opačném případě je operátor metoda vyvolána .x

Všimněte si, že vedlejší účinky jsou x vyhodnoceny pouze jednou v procesu.

Například:

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 ++() => ...;
}

Operátory přírůstku a dekrementace přípony

Viz https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12816-postfix-increment-and-decrement-operators.

Pokud je výsledek operace použit nebo x není x «op» klasifikován jako proměnná nebo je cílem staré jazykové verze, operace se zpracuje použitím rozlišení přetížení unárního operátoru, jak https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12816-postfix-increment-and-decrement-operators je aktuálně uvedeno. Důvodem, proč se při použití výsledku ani nepokoušíme operátory inkrementace instance, je skutečnost, že pokud pracujeme s odkazovým typem, není možné vytvořit hodnotu x před operací, pokud je používaná ztlumená. Pokud pracujeme s typem hodnoty, budeme muset přesto vytvořit kopie atd.

V opačném případě se priorita udělí operátorům inkrementace instancí následujícím způsobem.

Nejprve je proveden pokus o zpracování operace použitím operátoru zvýšení instance přetížení. Pokud proces nevygeneruje žádný výsledek a žádná chyba, operace se zpracuje použitím rozlišení přetížení unárního operátoru, jak https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12816-postfix-increment-and-decrement-operators je aktuálně uvedeno.

V opačném případě se operace x«op» vyhodnotí následujícím způsobem.

Je-li typ x známé jako referenční typ, je vyvolána metoda operátoru x. Pokud x je null, vyvolání metody operátoru vyvolá nullReferenceException.

Například:

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 ++() => ...;
}

Pokud typ x není znám jako referenční typ, je vyvolána metoda operátoru x.

Například:

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 ++() => ...;
}

Rozlišení přetížení operátoru inkrementace instance

Operace formuláře «op» x nebo x «op», kde «op» je přetížitelný inkrementovací operátor, a x je výraz typu X, je zpracován takto:

  • Sada kandidátských uživatelem definovaných operátorů poskytovaných X pro operaci operator «op»(x) je určena pomocí pravidel inkrementace instancí kandidáta.
  • Pokud sada kandidátských uživatelem definovaných operátorů není prázdná, stane se tím sada kandidátských operátorů pro operaci. V opačném případě rozlišení přetížení nepřináší žádný výsledek.
  • Pravidla rozlišení přetížení se použijí na sadu kandidátských operátorů pro výběr nejlepšího operátoru a tento operátor se stane výsledkem procesu řešení přetížení. Pokud se řešení přetížení nepodaří vybrat jeden nejlepší operátor, dojde k chybě doby vazby.

Operátory přírůstku instance kandidáta

Za předpokladu typu T a operace «op», kde «op» je přetížitelný operátor inkrementace instance, je sada kandidátských uživatelem definovaných operátorů T určena následujícím způsobem:

  • V unchecked kontextu vyhodnocení se jedná o skupinu operátorů, které by byly vytvořeny vyhledávacím procesem člena, pokud byly považovány pouze za operátory instanceoperator «op»(), které odpovídají cílovému názvu N.
  • V checked kontextu vyhodnocení se jedná o skupinu operátorů, které by byly vytvořeny vyhledávacím procesem člena, pokud by byly považovány pouze za instance a operátory instancí operator «op»()operator checked «op»(), které odpovídají cílovému názvu N. Operátory operator «op»() , které mají deklarace párového párování operator checked «op»() , jsou ze skupiny vyloučeny.

Složené přiřazení

Viz https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12214-compound-assignment.

Odstavec na začátku, který se zabývá dynamic , je stále použitelný tak, jak je.

Jinak platí, že pokud x je in x «op»= y klasifikovaný jako proměnná a cílí na novou jazykovou verzi, pak se priorita přiřadí operátorům složeného přiřazení následujícím způsobem.

Nejprve se pokusí zpracovat operaci formuláře x «op»= y použitím rozlišení přetížení operátoru složeného přiřazení. Pokud proces nevygeneruje žádný výsledek a žádná chyba, operace se zpracuje použitím rozlišení přetížení binárního operátoru, jak https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12214-compound-assignment je aktuálně uvedeno.

V opačném případě se operace vyhodnotí následujícím způsobem.

Pokud je typ x známé jako typ odkazu, je vyhodnocen k x získání instance x₀, operátor metoda je vyvolána na této instanci s argumentem y a x₀ je vrácena v důsledku složeného přiřazení. Pokud x₀ je null, vyvolání metody operátoru vyvolá nullReferenceException.

Například:

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) => ...;
}

Pokud typ x není znám jako odkazový typ:

  • Pokud se použije výsledek složeného přiřazení, x vyhodnotí se pro získání instance x₀, operátor metoda je vyvolána na této instanci s argumentem y , x₀ je přiřazena x a x₀ je vrácena v důsledku složeného přiřazení.
  • V opačném případě je metoda operátoru vyvolána x jako y argument.

Všimněte si, že vedlejší účinky jsou x vyhodnoceny pouze jednou v procesu.

Například:

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) => ...;
}

Rozlišení přetížení operátoru složeného přiřazení

Operace formuláře x «op»= y, kde «op»= je přetížitelný složený operátor přiřazení, x je výraz typu X je zpracován takto:

  • Sada kandidátských uživatelem definovaných operátorů poskytovaných X pro operaci operator «op»=(y) je určena pomocí pravidel kandidátských operátorů složeného přiřazení.
  • Pokud je pro seznam (y)argumentů použitelný alespoň jeden kandidáta uživatelem definovaný operátor v sadě , stane se sada kandidátských operátorů pro operaci. V opačném případě rozlišení přetížení nepřináší žádný výsledek.
  • Pravidla rozlišení přetížení se použijí na sadu kandidátských operátorů, aby vybrali nejlepší operátor s ohledem na seznam (y)argumentů a tento operátor se stane výsledkem procesu řešení přetížení. Pokud se řešení přetížení nepodaří vybrat jeden nejlepší operátor, dojde k chybě doby vazby.

Operátory složeného přiřazení kandidáta

Při zadání typu T a operace «op»=, kde «op»= je přetížitelný operátor složeného přiřazení, je sada kandidátských uživatelem definovaných operátorů T určena následujícím způsobem:

  • V unchecked kontextu vyhodnocení se jedná o skupinu operátorů, které by byly vytvořeny vyhledávacím procesem člena, pokud byly považovány pouze za operátory instanceoperator «op»=(Y), které odpovídají cílovému názvu N.
  • V checked kontextu vyhodnocení se jedná o skupinu operátorů, které by byly vytvořeny vyhledávacím procesem člena, pokud by byly považovány pouze za instance a operátory instancí operator «op»=(Y)operator checked «op»=(Y), které odpovídají cílovému názvu N. Operátory operator «op»=(Y) , které mají deklarace párového párování operator checked «op»=(Y) , jsou ze skupiny vyloučeny.

Otevřené otázky

[Vyřešeno] Má readonly být modifikátor povolen ve strukturách?

Zdá se, že neexistuje žádná výhoda, protože by bylo možné označit metodu, když readonly celý účel metody je upravit instanci.

Závěr: Modifikátory povolíme readonly , ale v tuto chvíli neuvolníme cílové požadavky.

[Vyřešeno] Má být povolené stínování?

Pokud odvozená třída deklaruje operátor inkrementace "složené přiřazení"/"instance se stejným podpisem jako v základu, měli bychom vyžadovat override modifikátor?

Závěr: Stínování bude povoleno se stejnými pravidly jako metody.

[Vyřešeno] Měli bychom mít zajištění konzistentnosti mezi deklarovanými operátory += a +?

Během LDM-2025-02-12 byla vyjádřena obava, že autoři svými omyly zatlačí své uživatele do nestandardních scénářů, kdy += může fungovat, ale + nebude (nebo naopak), protože jedna forma deklaruje více operátorů než druhá.

Závěr: Kontroly ohledně konzistence nebudou prováděny u různých typů operátorů.

Alternativy

Použití statických metod

Mohli bychom zvážit použití statických operátorů metod, kdy se instance, která má být ztlumená, předána jako první parametr. V případě typu hodnoty musí být tento parametr parametrem ref . Jinak metoda nebude moct ztlumit cílovou proměnnou. Současně by tento parametr neměl být parametrem ref v případě typu třídy. Protože v případě třídy musí být předaný v instanci mutován, nikoli umístění, kde je instance uložena. Pokud je však operátor deklarován v rozhraní, není často známo, zda bude rozhraní implementováno pouze třídami, nebo pouze strukturami. Proto není jasné, zda má být prvním parametrem ref parametr.

Designérské schůzky