Opérateurs surchargés, depuis MSDN:
Les opérateurs d'assignation ne peuvent pas être surchargés, mais +=
, par exemple, est évalué en utilisant +
, qui peut être surchargé.
De plus, aucun des opérateurs d'assignation ne peut être surchargé. Je pense que c'est parce qu'il y aura un effet sur la collecte des déchets et la gestion de la mémoire, ce qui constitue une faille de sécurité potentielle dans le monde fort typé du CLR.
Néanmoins, voyons ce qu'est exactement un opérateur. Selon le célèbre livre de Jeffrey Richter, chaque langage de programmation a sa propre liste d'opérateurs, qui sont compilés dans des appels de méthodes spéciales, et le CLR lui-même ne sait rien des opérateurs. Alors voyons ce qui se cache exactement derrière les opérateurs +
et +=
.
Regardez ce code simple :
Décimal d = 10M;
d = d + 10M;
Console.WriteLine(d);
Voyons le code IL pour ces instructions :
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldc.i4.s 10
IL_000c: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0011: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Addition(valuetype [mscorlib]System.Decimal,
valuetype [mscorlib]System.Decimal)
IL_0016: stloc.0
Passons maintenant à ce code :
Décimal d1 = 10M;
d1 += 10M;
Console.WriteLine(d1);
Et le code IL pour cela :
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldc.i4.s 10
IL_000c: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0011: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Addition(valuetype [mscorlib]System.Decimal,
valuetype [mscorlib]System.Decimal)
IL_0016: stloc.0
ils sont égaux! Donc l'opérateur +=
est simplement du sucre syntaxique pour votre programme en C#, et vous pouvez simplement surcharger l'opérateur +
.
Par exemple :
class Foo
{
private int c1;
public Foo(int c11)
{
c1 = c11;
}
public static Foo operator +(Foo c1, Foo x)
{
return new Foo(c1.c1 + x.c1);
}
}
static void Main(string[] args)
{
Foo d1 = new Foo (10);
Foo d2 = new Foo(11);
d2 += d1;
}
Ce code sera compilé et exécuté avec succès comme :
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: newobj instance void ConsoleApplication2.Program/Foo::.ctor(int32)
IL_0008: stloc.0
IL_0009: ldc.i4.s 11
IL_000b: newobj instance void ConsoleApplication2.Program/Foo::.ctor(int32)
IL_0010: stloc.1
IL_0011: ldloc.1
IL_0012: ldloc.0
IL_0013: call class ConsoleApplication2.Program/Foo ConsoleApplication2.Program/Foo::op_Addition(class ConsoleApplication2.Program/Foo,
class ConsoleApplication2.Program/Foo)
IL_0018: stloc.1
Mise à jour :
Conformément à votre mise à jour - comme le dit @EricLippert, vous devriez vraiment avoir les vecteurs en tant qu'objet immuable. Le résultat de l'addition des deux vecteurs est un nouveau vecteur, pas le premier avec des tailles différentes.
Si, pour une raison quelconque, vous avez besoin de modifier le premier vecteur, vous pouvez utiliser cette surcharge (mais selon moi, c'est un comportement très étrange) :
public static Vector operator +(Vector left, Vector right)
{
left.x += right.x;
left.y += right.y;
return left;
}
2 votes
Il semble qu'une longue discussion ait déjà eu lieu à ce sujet: maurits.wordpress.com/2006/11/27/…
39 votes
Pouvez-vous expliquer pourquoi vous essayez de faire cela? Vous obtenez gratuitement un opérateur "+=" surchargé lorsque vous surchargez "+". Y a-t-il une situation dans laquelle vous voulez que "+=" soit surchargé mais ne voulez pas que "+" soit surchargé?
3 votes
En venant de C ++, cela semble juste faux, mais en C #, cela a en fait tout son sens.
2 votes
Possible duplicate of Pourquoi ne puis-je pas surcharger l'opérateur += en C# ? Mais je peux toujours l'utiliser ?
0 votes
J'ai ajouté une explication de pourquoi j'ai besoin de cela.
13 votes
@Mathias: concernant votre mise à jour: Les vecteurs doivent se comporter comme des objets mathématiques immuables. Lorsque vous ajoutez 2 à 3, vous ne muter pas l'objet 3 en l'objet 5. Vous créez un tout nouvel objet, 5. Le but de surcharger les opérateurs d'addition est de créer vos propres objets mathématiques ; les rendre mutables va à l'encontre de cet objectif. Je ferais de votre type de vecteur un type de valeur immuable.
1 votes
@EricLippert : Si
SomeEvent
est un événement,SomeEvent += SomeDelegate
a une signification très différente deSomeEvent = SomeEvent + SomeDelegate
. De plus, même siVector
était un type à mutation externe, avoirvec1 += vec2;
traduit enVector.AddTo(ref Vector dest, Vector src);
pourrait offrir les mêmes sémantiques quedest = dest + src;
mais sans opérations redondantes de copie de structure.