User defined compound assignment operators #9100
-
Champion issue: #9101 Allow user types to customize behavior of compound assignment operators in a way that the target of the assignment is MotivationC# provides support for the developer overloading operator implementations for user-defined type. Given the following example 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();
} with the current language rules, compound assignment operator When a program utilizes a compound assignment operation, the most common effect is that the original value is Therefore, it may be beneficial for C# to allow user types to |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 9 replies
-
For functional and immutability perspective, how to make sure the instance isn't shared inappropriately? Like: BigInteger a = 1;
BigInteger b = a;
a += 1; Should this be equivalent to the following? BigInteger a = 1;
BigInteger b = a;
a = a + 1; It may also cause concern about thread safety etc. In other words, reusing storages in compound assignment are only safe if unique ownership is provided. Although this doesn't affect the operator support in C# itself, it can affect API designs leveraging this pattern. Can we provide more? |
Beta Was this translation helpful? Give feedback.
-
I was excited to see this feature proposal :)
Re this: allowing Also, another question is how it works in |
Beta Was this translation helpful? Give feedback.
-
As noted in another answer, this proposal does not add much (if anything) for the existing kinds of types. However, for move-only types it does add new capabilities. If you have a move-only type behind a The workaround with the existing language is to use a method which can take A subtle side effect of the proposal will be that the order of evaluation will be different for types that adopt user-defined compound assignment operators. Normally, A contrived example: int x = 1;
x += f();
Console.WriteLine($"x = {x}");
int f() {
x = 100;
return 4;
} This prints |
Beta Was this translation helpful? Give feedback.
-
The spec proposes that when there is an overload resolution failure among declared compound operators (e.g. This makes it a breaking change to add any compound assignment operator to a type in the following scenario: var x = new MyType();
x += 4; // Breaks if the `+=(MyType, MyType)` operator below is added, and the `+=(MyType, int)` operator is overlooked.
class MyType
{
public void operator +=(MyType right) => ...
public static MyType operator +(MyType left, MyType right) => ...
public static MyType operator +(MyType left, int right) => ...
// Irrelevant to the example, but often declared:
public static MyType operator +(int left, MyType right) => ...
} For safety, if any particular compound operator is declared, I propose a compiler warning if it is missing any overloads that are present among its matching non-compound operator declarations. (Non-compound operator overloads where the first operand is a different type can't have a compound operator counterpart, and are ignored for this check.) |
Beta Was this translation helpful? Give feedback.
This doesn't look like an accurate interpretation of the spec. The added operator won't be applicable, therefore, it won't prevent use of a
+
. Fall back won't happen only in presence of applicable to the arguments instance operators.