Aracılığıyla paylaş


Kullanıcı Tanımlı Bileşik Atama İşleçleri

Uyarı

Bu makale bir özellik belirtimidir. Belirtim, özelliğin tasarım belgesi olarak görev alır. Önerilen belirtim değişikliklerini ve özelliğin tasarımı ve geliştirilmesi sırasında gereken bilgileri içerir. Bu makaleler, önerilen belirtim değişiklikleri son haline getirilene ve geçerli ECMA belirtimine dahil edilene kadar yayımlanır.

Özellik belirtimi ile tamamlanan uygulama arasında bazı tutarsızlıklar olabilir. Bu farklılıklar ilgili dil tasarım toplantısı (LDM) notlarında yakalanır.

Özellik belirtimlerini C# dil standardına benimseme işlemi hakkında daha fazla bilgi edinmek içinbelirtimleri makalesinde bulabilirsiniz.

Şampiyonluk sorunu: https://github.com/dotnet/csharplang/issues/9101

Özet

Kullanıcı türlerinin bileşik atama işleçlerinin davranışını atamanın hedefi yerinde değiştirildiği şekilde özelleştirmesine izin verin.

Motivasyon

C# kullanıcı tanımlı tür için geliştirici aşırı yükleme işleci uygulamaları için destek sağlar. Buna ek olarak, kullanıcının yerine benzer şekilde x += yx = x + ykod yazmasına olanak tanıyan "bileşik atama işleçleri" için destek sağlar. Ancak, dil şu anda geliştiricinin bu bileşik atama işleçlerini aşırı yüklemesine izin vermez ve varsayılan davranış doğru şeyi yaparken, özellikle sabit değer türleriyle ilgili olduğu için her zaman "en iyi" değildir.

Aşağıdaki örnek göz önünde bulundurulduğunda

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

geçerli dil kurallarıyla, bileşik atama işleci c1 += 1 kullanıcı tanımlı + işlecini çağırır ve ardından dönüş değerini yerel değişkenine c1atar. Operatör uygulamasının yeni bir örneğini C1ayırması ve döndürmesi gerekirken, tüketicinin perspektifinden, bunun yerine özgün örneğine C1 yerinde bir değişiklik iyi çalışır (atamadan sonra kullanılmaz), ek ayırmadan kaçınmanın bir avantajı vardır.

Bir program bileşik atama işlemi kullandığında, en yaygın etki özgün değerin "kaybedilmiş" olması ve artık program tarafından kullanılamamadır. Büyük veri içeren türlerde (BigInteger, Tensors vb.) net yeni bir hedef oluşturmanın, belleği yinelemenin ve kopyalamanın maliyeti oldukça pahalıdır. Yerinde bir mutasyon birçok durumda bu giderin atlanmasına olanak sağlar ve bu da bu tür senaryolarda önemli iyileştirmeler sağlayabilir.

Bu nedenle, C# için kullanıcı türlerinin bileşik atama işleçlerinin davranışını özelleştirmesine ve aksi takdirde ayırması ve kopyalaması gerekebilecek senaryoları iyileştirmesine izin vermek yararlı olabilir.

Ayrıntılı tasarım

Sözdizimi

konumundaki https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/classes.md#15101-general dil bilgisi aşağıdaki gibi ayarlanır.

İşleçler operator_declarationkullanılarak bildirilir:

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

Beş aşırı yüklenebilir işleç kategorisi vardır: birli işleçler, ikili işleçler, dönüştürme işleçleri, artım işleçleri, bileşik atama işleçleri.

Aşağıdaki kurallar tüm işleç bildirimleri için geçerlidir:

  • İşleç bildirimi hem a publicstatichem de değiştirici içermelidir.

Bileşik atama ve örnek artışı işleçleri, temel sınıfta bildirilen işleçleri gizleyebilir. Bu nedenle, aşağıdaki paragraf artık doğru değildir ve buna göre ayarlanmalıdır veya kaldırılabilir:

İşleç bildirimleri her zaman işlecin işlecin imzasına katılmak üzere bildirildiği sınıf veya yapıyı gerektirdiğinden, türetilmiş bir sınıfta bildirilen bir işlecin temel sınıfta bildirilen bir işleci gizlemesi mümkün değildir. Bu nedenle, new değiştirici bir işleç bildiriminde hiçbir zaman gerekli değildir ve bu nedenle hiçbir zaman izin verilmez.

Tekli operatörler

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

Operatör bildiriminde değiştirici static bulunacaktır ve değiştirici içermeyecektir override .

Aşağıdaki madde işareti kaldırılır:

  • Bir birli ++ veya -- işleç, tek bir tür T parametresini alacaktır veya T? aynı türde veya ondan türetilmiş bir tür döndürecektir.

Aşağıdaki paragraf artık bahsetme ++-- ve işleç belirteçleri olmayacak şekilde ayarlanır:

Birli işlecin imzası, işleç belirtecini (+, -, !, , ~, ++, --veya truefalse) ve tek parametrenin türünden oluşur. Dönüş türü, birli işlecin imzasının bir parçası değildir ve parametrenin adı değildir.

Bölümdeki bir örnek, kullanıcı tanımlı bir artım işleci kullanmamak için ayarlanmalıdır.

İkili işleçler

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

Operatör bildiriminde değiştirici static bulunacaktır ve değiştirici içermeyecektir override .

Dönüştürme işleçleri

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

Operatör bildiriminde değiştirici static bulunacaktır ve değiştirici içermeyecektir override .

Artım işleçleri

Aşağıdaki kurallar, T işleç bildirimini içeren sınıfın veya yapının örnek türünü belirten statik artış işleci bildirimleri için geçerlidir:

  • Operatör bildiriminde değiştirici static bulunacaktır ve değiştirici içermeyecektir override .
  • Bir işleç, veya türünde TT? tek bir parametre alacaktır ve aynı türü veya ondan türetilmiş bir türü döndürecektir.

Statik artış işlecinin imzası işleç belirteçlerinden ('checked'? ++, 'checked'? --) ve tek parametrenin türünden oluşur. Dönüş türü, statik artış işlecinin imzasının bir parçası değildir ve parametrenin adı değildir.

Statik artış işleçleri birli işleçlere çok benzer.

Aşağıdaki kurallar örnek artım işleci bildirimleri için geçerlidir:

  • İşleç bildiriminde değiştirici bulunmayacak static .
  • Bir işleç parametre almayacaktır.
  • Bir işleç dönüş türüne sahip void olmalıdır.

Etkili bir şekilde örnek artırma işleci, parametresi olmayan ve meta verilerde özel bir adı olan geçersiz bir dönüş örneği yöntemidir.

Örnek artım işlecinin imzası işleç belirteçlerinden ('checked'? '++' | 'checked'? '--') oluşur.

Bildirim checked operator için bir çifte göre bildirimi gerekir regular operator. Aksi takdirde derleme zamanı hatası oluşur. Ayrıca bkz. https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/checked-user-defined-operators.md#semantics.

yönteminin amacı, istenen artım işleminin sonucu olarak, bildirim türü bağlamında ne anlama geliyorsa, örneğin değerini ayarlamaktır.

Örnek:

class C1
{
    public int Value;

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

Örnek artım işleci, temel sınıfta bildirilen aynı imzaya sahip bir işleci geçersiz kılabilir, bu amaçla bir override değiştirici kullanılabilir.

Artırma/azaltma işleçlerinin örnek sürümlerini desteklemek için ECMA-335'e aşağıdaki "ayrılmış" özel adlar eklenmelidir: | Ad | İşleç | | -----| -------- | |op_DecrementAssignment| -- | |op_IncrementAssignment| ++ | |op_CheckedDecrementAssignment| denetlendi -- | |op_CheckedIncrementAssignment| işaretli ++ |

Bileşik atama işleçleri

Bileşik atama işleci bildirimleri için aşağıdaki kurallar geçerlidir:

  • İşleç bildiriminde değiştirici bulunmayacak static .
  • Bir işleç bir parametre alacaktır.
  • Bir işleç dönüş türüne sahip void olmalıdır.

Etkili bir şekilde bileşik atama işleci, tek bir parametre alan ve meta verilerde özel bir ada sahip geçersiz bir dönüş örneği yöntemidir.

Bileşik atama operatörünün imzası, operatör belirteçlerinden ('kontrollü' mi? '+=', 'kontrollü' mi? '-=', 'kontrollü' mi? '*=', 'kontrollü' mi? '/=', '%=', '&=', '|=', '^=', '<<=', sağa kaydırma ataması, işaretsiz sağa kaydırma ataması) ve tek parametrenin türünden oluşur. parametresinin adı bileşik atama işlecinin imzasının bir parçası değildir.

Bildirim checked operator için bir çifte göre bildirimi gerekir regular operator. Aksi takdirde derleme zamanı hatası oluşur. Ayrıca bkz. https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/checked-user-defined-operators.md#semantics.

yönteminin amacı, örneğin değerini sonucu olarak ayarlamaktır <instance> <binary operator token> parameter.

Örnek:

class C1
{
    public int Value;

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

Bileşik atama işleci, temel sınıfta bildirilen aynı imzaya sahip bir işleci geçersiz kılabilir, bu amaçla bir override değiştirici kullanılabilir.

ECMA-335 kullanıcı tanımlı artım işleçleri için şu özel adları zaten "ayrılmıştır": | Ad | İşleç | | -----| -------- | |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|

Ancak, CLS uyumluluğunun işleç yöntemlerinin iki parametreyle geçersiz olmayan statik yöntemler olmasını gerektirdiğini belirtir; yani C# ikili işleçlerinin ne olduğuyla eşleşir. Operatörlerin tek bir parametreyle dönüş örneği yöntemlerini geçersiz kılabilmesi için CLS uyumluluk gereksinimlerini gevşetmeyi düşünmeliyiz.

İşleçlerin denetlenen sürümlerini desteklemek için aşağıdaki adlar eklenmelidir: | Ad | İşleç | | -----| -------- | |op_CheckedAdditionAssignment| işaretli '+=' | |op_CheckedSubtractionAssignment| işaretli '-=' | |op_CheckedMultiplicationAssignment| işaretli '*=' | |op_CheckedDivisionAssignment| işaretli '/=' |

Önek arttırma ve azaltma işleçleri

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

içinde x bir değişken olarak sınıflandırılırsa ve yeni bir dil sürümü hedefleniyorsa«op» x, öncelik aşağıdaki gibi örnek artırma işleçlerine verilir.

İlk olarak, örnek artım işleci aşırı yükleme çözümlemesi uygulanarak işlemi işlemeye çalışılır. İşlem sonuç ve hata üretmezse, işlem şu anda belirtildiği gibi https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#1296-prefix-increment-and-decrement-operators birli işleç aşırı yükleme çözümlemesi uygulanarak işlenir.

Aksi takdirde, bir işlem «op»x aşağıdaki gibi değerlendirilir.

türü x bir başvuru türü olarak biliniyorsa, x örneği almak x₀için değerlendirilir, işleç yöntemi bu örnekte çağrılır ve x₀ işlemin sonucu olarak döndürülür. ise x₀null, işleç yöntemi çağrısı nullReferenceException oluşturur.

Örneğin:

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

türü x bir başvuru türü olarak bilinmiyorsa:

  • Artış sonucu kullanılırsa, x örneği x₀almak için değerlendirilir, işleç yöntemi bu örnekte çağrılır, x₀ öğesine atanır x ve x₀ bileşik atamanın sonucu olarak döndürülür.
  • Aksi takdirde işleç yöntemi üzerinde xçağrılır.

içindeki x yan etkilerin işlemde yalnızca bir kez değerlendirildiğini unutmayın.

Örneğin:

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

Sonek artış ve azaltma işleçleri

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

İşlemin sonucu kullanılırsa veya x içinde x «op» değişken olarak sınıflandırılmazsa veya eski bir dil sürümü hedefleniyorsa, işlem şu anda belirtildiği gibi https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12816-postfix-increment-and-decrement-operators birli işleç aşırı yükleme çözümlemesi uygulanarak işlenir. Sonuç kullanıldığında örnek artırma işleçlerini denememe nedenimiz, bir başvuru türüyle ilgileniyorsak, yerinde sessize alındıysa işlemden önce değerinin x üretilmemesidir. Bir değer türüyle karşı karşıyaysak, yine de kopya yapmamız gerekir.

Aksi takdirde, öncelik aşağıdaki gibi örnek artım işleçlerine verilir.

İlk olarak, örnek artım işleci aşırı yükleme çözümlemesi uygulanarak işlemi işlemeye çalışılır. İşlem sonuç ve hata üretmezse, işlem şu anda belirtildiği gibi https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12816-postfix-increment-and-decrement-operators birli işleç aşırı yükleme çözümlemesi uygulanarak işlenir.

Aksi takdirde, bir işlem x«op» aşağıdaki gibi değerlendirilir.

türü x bir başvuru türü olarak biliniyorsa, işleç yöntemi üzerinde xçağrılır. ise xnull, işleç yöntemi çağrısı nullReferenceException oluşturur.

Örneğin:

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

türü x bir başvuru türü olarak bilinmiyorsa, işleç yöntemi üzerinde xçağrılır.

Örneğin:

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

Örnek artış işleci aşırı yükleme çözümlemesi

veya biçimindeki «op» x bir işlem; burada «op» aşırı yüklenebilir bir örnek artım işlecidir ve x «op» türünde xbir ifadedir:X

  • tarafından işlem X için sağlanan operator «op»(x) aday kullanıcı tanımlı işleç kümesi, aday örneği artım işleçleri kuralları kullanılarak belirlenir.
  • Kullanıcı tanımlı aday işleç kümesi boş değilse, bu işlem için aday işleç kümesi olur. Aksi takdirde aşırı yükleme çözümlemesi sonuç vermez.
  • En iyi işleci seçmek için aday işleç kümesine aşırı yükleme çözümleme kuralları uygulanır ve bu işleç aşırı yükleme çözümleme işleminin sonucu olur. Aşırı yükleme çözümlemesi tek bir en iyi işleci seçemezse bağlama zamanı hatası oluşur.

Aday örneği artım işleçleri

Bir tür T ve bir işlem «op»verildiğinde «op» , burada aşırı yüklenebilir bir örnek artış işleci, tarafından T sağlanan aday kullanıcı tanımlı işleçler kümesi aşağıdaki gibi belirlenir:

  • Değerlendirme unchecked bağlamında, yalnızca örnek işleçlerinin hedef adıyla operator «op»()eşleştiği kabul edildiğinde Üye aramaNoluşturulacak bir işleç grubudur.
  • Değerlendirme checked bağlamında, yalnızca örnek ve örnek operator «op»() işleçlerinin hedef adla operator checked «op»()eşleştiği kabul edildiğinde Üye aramaNoluşturulacak bir işleç grubudur. Çifte operator «op»() göre eşleşen operator checked «op»() bildirimleri olan işleçler gruptan dışlanır.

Bileşik atama

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

En başındaki ile dynamic ilgilenen paragraf olduğu gibi hala geçerlidir.

Aksi takdirde, x içinde x «op»= y bir değişken olarak sınıflandırılır ve yeni bir dil sürümü hedeflenirse, öncelik aşağıdaki gibi bileşik atama işleçlerine verilir.

İlk olarak, bileşik atama işleci aşırı yükleme çözümlemesix «op»= yformun bir işlemini işlemeye çalışılır. İşlem sonuç ve hata üretmezse, işlem şu anda belirtildiği gibi https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12214-compound-assignment ikili işleç aşırı yükleme çözümlemesi uygulanarak işlenir.

Aksi takdirde, işlem aşağıdaki gibi değerlendirilir.

türü x bir başvuru türü olarak biliniyorsa, x bir örneği x₀almak için değerlendirilir, işleç yöntemi bağımsız değişken olarak bu örnekte y çağrılır ve x₀ bileşik atamanın sonucu olarak döndürülür. ise x₀null, işleç yöntemi çağrısı nullReferenceException oluşturur.

Örneğin:

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

türü x bir başvuru türü olarak bilinmiyorsa:

  • Bileşik atamanın sonucu kullanılırsa, x örneği almak x₀için değerlendirilir, işleç yöntemi bu örnekte y bağımsız değişken olarak çağrılır, x₀ öğesine atanır x ve x₀ bileşik atamanın sonucu olarak döndürülür.
  • Aksi takdirde, işleç yöntemi ile bağımsız değişken olarak çağrılır xy .

içindeki x yan etkilerin işlemde yalnızca bir kez değerlendirildiğini unutmayın.

Örneğin:

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

Bileşik atama işleci aşırı yükleme çözümlemesi

aşırı yüklenebilir bir bileşik atama işleci olan x «op»= y formunun «op»=bir işlemi, x türündeki X bir ifade aşağıdaki gibi işlenir:

  • tarafından işlem X için sağlanan operator «op»=(y) aday kullanıcı tanımlı işleç kümesi, aday bileşik atama işleçlerinin kuralları kullanılarak belirlenir.
  • Kümedeki en az bir aday kullanıcı tanımlı işleç bağımsız değişken listesi (y)için geçerliyse, bu işlem için aday işleç kümesi olur. Aksi takdirde aşırı yükleme çözümlemesi sonuç vermez.
  • Aşırı yükleme çözümleme kuralları , bağımsız değişken listesine (y)göre en iyi işleci seçmek için aday işleç kümesine uygulanır ve bu işleç aşırı yükleme çözümleme işleminin sonucu olur. Aşırı yükleme çözümlemesi tek bir en iyi işleci seçemezse bağlama zamanı hatası oluşur.

Aday bileşik atama işleçleri

Bir tür T ve bir işlem «op»=verildiğinde «op»= , burada aşırı yüklenebilir bir bileşik atama işlecidir, tarafından T sağlanan aday kullanıcı tanımlı işleç kümesi aşağıdaki gibi belirlenir:

  • Değerlendirme unchecked bağlamında, yalnızca örnek işleçlerinin hedef adıyla operator «op»=(Y)eşleştiği kabul edildiğinde Üye aramaNoluşturulacak bir işleç grubudur.
  • Değerlendirme checked bağlamında, yalnızca örnek ve örnek operator «op»=(Y) işleçlerinin hedef adla operator checked «op»=(Y)eşleştiği kabul edildiğinde Üye aramaNoluşturulacak bir işleç grubudur. Çifte operator «op»=(Y) göre eşleşen operator checked «op»=(Y) bildirimleri olan işleçler gruptan dışlanır.

Açık sorular

[Çözüldü] Yapılarda değiştiriciye izin verilmeli mi readonly ?

Yöntemin amacının tamamının örneği değiştirmek olduğu durumlarda ile bir yöntemin readonly işaretlenmesine izin vermenin bir yararı olmayacak gibi görünüyor.

Son: Değiştiricilere izin readonly yeceğiz, ancak şu anda hedef gereksinimleri gevşetmeyeceğiz.

[Çözüldü] Gölgelendirmeye izin verilmeli mi?

Türetilmiş bir sınıf, temeldeki imzayla aynı imzaya sahip bir 'bileşik atama'/'örnek artışı' işlecini bildirirse, bir override değiştiriciye ihtiyacımız var mı?

Son: Gölgelendirmeye yöntemlerle aynı kurallarla izin verilir.

[Çözüldü] Bildirilen += ve + işleçler arasında herhangi bir tutarlılık zorlaması olması gerekir mi?

LDM-2025-02-12 sırasında, yazarların kullanıcılarını bir form diğerinden daha fazla işleç bildirdiği için bir += çalışırken + çalışmayabileceği (veya tersi) garip senaryolara yanlışlıkla sürükleyebilecekleri konusunda endişe dile getirildi.

Son: Farklı işleç biçimleri arasındaki tutarlılık üzerinde denetimler yapılmaz.

Alternatifler

Statik yöntemleri kullanmaya devam edin

Sessize alınacak örneğin ilk parametre olarak geçirildiği statik işleç yöntemlerini kullanmayı düşünebiliriz. Değer türü söz konusu olduğunda, bu parametre bir ref parametre olmalıdır. Aksi takdirde yöntemi hedef değişkenin sesini kapatamaz. Aynı zamanda, bir sınıf türü söz konusu olduğunda, bu parametre bir ref parametre olmamalıdır. Bir sınıf olması durumunda geçirilen örneğin, örneğin depolandığı konumu değil, sessize alınması gerekir. Ancak, bir işleç bir arabirimde bildirildiğinde, genellikle arabirimin yalnızca sınıflar tarafından mı yoksa yalnızca yapılar tarafından mı uygulanacağı bilinmez. Bu nedenle, ilk parametrenin parametre ref olup olmadığı net değildir.

Tasarım toplantıları