How to use the symbols +=, *=,-= - c#

These operands may be simple but the difficulty of finding explanations which are definitive and complete prompted me to ask. What are the character combinations containing an operand followed by an equal sign (such as *=, -=,+=, etc), what do they do and how are they useful (especially pertaining to non-numeric fields)?
Examples as well as definitions would be greatly appreciated.
Thanks

They are usually interpreted broadly as:
x += y === x = x + y
(etc for your choice of operator)
however; some languages allow you to have a bespoke += operator*, or may interpret it differently in some scenarios; for example, in C# events, += and -= mean "subscribe via the add accessor" and "unsubscribe via the remove accessor" respectively.
Typically they are just space savers, but there can be semantic differences in some cases.
*=where I mean: very different to just the + operator and assignment

Pretty much all the answers here state that x += y; is "equivalent" to "x = x + y;".
This is not actually true. They are not exactly equivalent for several reasons.
First, side effects are only performed once. Suppose you have
class C { public string S { get; set; } }
class D
{
private static C c = new C();
static C M()
{
Console.WriteLine("hello!");
return c;
}
}
The first line below prints "hello" once, as you would expect. The second prints it twice.
D.M().S += "abc";
D.M().S = D.M().S + "abc";
Second, the type system works differently for compound assignment than for regular assignment.
short b = 1;
short c = 2;
b += c;
b = b + c;
The third line is legal. The fourth line is not; a short plus a short is an int in C#, so b = b + c is an illegal assigning of an int to a short. In this case the compound assignment is actually equivalent to b = (short)(b + c);
If this subject interests you I encourage you to read sections 7.17.2 and 7.17.3 of the C# specification.

The great advantage is that you can say:
x += y;
Instead of the more verbose:
x = x + y;
Sometimes this is nice when working with strings, as you can use += to append text to an existing string.

x += expression is roughly the same thing as x = x + (expression). In other words, it calculates the right-hand side, then applies the + operator to the left-hand side and the result, and then assigns that result back into the left-hand side.
Personally, I'm not a huge fan of them. The /= operator I find a particular menace, as there are many Pascal-related languages that use that to indicate boolean inequality. Someone familiar with that who gets mixed up and tries to use it in C ends up with compiling code that produces some of the most bizzare bugs imagineable.
However, they do come in quite handy when the left-hand side is kind of large, so repeating it would throw out more noise than enlightenment.

These are compound assignment operators. For numeric fields, they're defined to add (+=), multiply (*=), and subtract (-=) the value on the right- from the variable on the left, and assign the result to the variable on the left.
However, C++ supports "operator overloading". Meaning, for any given object, the programmer can define what happens if you write x += 12 and x happens to be an object of type Foo rather than an int. This is commonly done for string classes, so if s1 = "All this" you can write s1 += " and more" and the result will be "All this and more".

Say you have x = 5. If you want to add 1 to x, you can do it in many ways:
x = x + 1;
x += 1;
x++;
++x;
They're all equivalent, and choosing any of those should leave x with 6.
So basically, if you want to multiply, divide, or subtract from x, just change the + operator to what you want.
Sorry, I didn't see that you mentioned non-numeric fields. In C# and in C++, you can do something called an "operator overload" to give a non-numeric object the ability to utilize these compound operators with a user-defined function and/or comparison.
For instance, strings are generally treated as objects and not as primitive data types, but if you execute String s = "hello"; s += "!";, you'll see that s will contain hello!. That's because the String object has an overloaded operator for += that applies an append with the rvalue ("!"--right of the += operator) to the lvalue ("hello"--left of the += operator).
A related question on C# operator overloading:
Simple way to overload compound assignment operator in C#?

If you want an explanation try reading http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Compound-assignment_operators like someone already suggested, basically a += b; is equivalent to a = a + b;. It's shorthand to make your code easier to write and read.
Here are some examples:
/* Print all evens from 0 through 20 */
for(i = 0; i <= 20; i += 2){
printf("%d\n", i);
}
/* Slow down at a linear pace */
/* Stop after speed is 0.1 or less */
while(speed > 0.1){
speed /= 1.2;
}
speed = 0;
Those should explain it. It applies to bitwise operations as well as arithmetic, but I can't think of any simple uses off the top of my head and I don't want to confuse you. There's the old temp-less swap trick - a ^= b ^= a ^= b; - which will swap the values of a and b without you having to create a temporary variable, but I'm not sure if you know what the bitwise XOR operation is at this point, so don't read into it yet.

With regard to non-numeric fields: what the operators do is completely arbitrary. In C/++/#, you can override what an operator does, allowing you to write something like:
MyObj += MyOtherObj;
// MyObj is now null
When overloading the operators, you can really do whatever you like.

Related

Accesing a member directly by the class name

Im trying to create a ufloat class/struct in c#. It's more of a challenge for me, but would help me control some values in code. After trying a couple of approaches, I finally have one that seems to work:
public struct ufloat
{
public float Value
{
get{ return value; }
set
{
if(value < 0)
{
this.value = 0;
}
else
{
this.value = Math.Abs(value);
}
}
}
}
The problem is, I want it to behave like a typical basic type:
ufloat n = 5;
n += 1;
After some thinking I tried to overload the '=' operator, but it is not possible. Now I am out of ideas. This is why I ask, how can you change this:
ufloat x; x.value = 1;
to this:
ufloat x = 0; x = 1;
?
(Sorry if I am losing something really easy, but I am a self-taught "programmer" and I am pretty new to c#. I learnt c++ at first, and going from lower to higher level isn't easy for me.)
You can't overload the = operator, but you can overload the + operator, and then the += operator (which I believe you meant instead of =+) will work in a reasonably obvious way. You'd also need to add an implicit conversion from float to your struct though.
I would strongly advise not making the struct mutable though - instead, let the + operator return a new value. That will make it behave like every other primitive type, and like most other structs. I'd also rename it to USingle to follow the normal .NET naming conventions (where Single is the CLR name for float). You can't add your own C# alias for a name like float is for Single though.
I suspect your type will want:
A constructor accepting a float
Conversions to and from float (note that normally implicit conversions shouldn't throw exceptions - you may want to ignore that, but I'm not sure...)
Overloads for the arithmetic operators (+, -, * and /)
Overrides of ToString, Equals and GetHashCode
Implementation of IComparable<USingle> and IEquatable<USingle>
You should think about what you want to happen if you add two values which are "large positive floats" together - is the intention that your new type is able to support larger positive values than float can, or is it just "float but always non-negative"?
You can not overload = operator but you may write implicit casts, for example this one is for casting an int:
public class ufloat
{
public float value { get; }
public ufloat(int val) { value = Math.Abs(val); }
public static implicit operator ufloat(int input)
{
return new ufloat(input);
}
}
Now if you assign an int value to it, it will implicitly be converted to ufloat:
ufloat x = -5;

C# What does int i = +1 mean?

I was browsing around stack overflow and I encountered this question:
check for duplicate filename when copying files in C#
In this question, this little gem existed:
int i = +1
I have never seen this syntax before. So I opened up the interactive C# window in visual studio:
Microsoft (R) Roslyn C# Compiler version 1.3.4.60902
Loading context from 'CSharpInteractive.rsp'.
Type "#help" for more information.
> int i = +1;
> i
1
> +1 == 1
true
Is this similar to +=? Is this some new syntax? What is this operator? How is it different than a normal variable declaration?
That's the unary plus operator. From the documentation:
The result of a unary + operation on a numeric type is just the value of the operand.
In most sane contexts1 where you're writing code, it'll be optional (+1 is the same as 1 if we're writing literals).
It mostly exists for symmetry with the unary minus operator.
Most of the time, you'll not write code containing it, but if you're generating code it can be handy to be able to apply a unary operator either way2.
It has no relation to +=.
1Insane code could override this operator for custom types and make it more than a no-op. But I'd love to understand a use case where it makes code more understandable, which should be the main aim of most code.
2E.g. imagine you're chaining a set of operations together and for each additional element, you wish to change the sign of the overall result. This lets you just store an operator and apply it blindly when you finally decide to output a result
For for all signed numeric types the positive-sign is optional. So,
+1 == (+1) == 1
+1.0 == (+1.0) == 1.0
+1L == (+1L) == 1L
+1.0m == (+1.0m) == 1.0m
Do not confuse
int i = +1; // Assigns 1
which is the same as
int i = (+1); // Assigns 1
or simply
int i = 1; // Assigns 1
with
int i += 1; // INCREMENT!
which increments i.
In C# terms there is a binary + operator (the addition operator as in int i = 3 + 4;) and a unary + operator (the plus sign as in int i = +1;).
Think of it the way you think of
int i = -1
and it becomes obvious

Is a += b operator of char implemented same as a = a + b? [duplicate]

This question already has answers here:
Difference between a+=1 and a=a+1 in C#
(3 answers)
Closed 5 years ago.
Found an interesting issue that following code runs with a different result:
char c = 'a';
c += 'a'; //passed
c = c + 'a'; //Cannot implicitly convert type 'int' to 'char'. An explicit conversion exists (are you missing a cast?)
Is there any difference between a += b and a=a+b, or just compiler's code check missed it?
My point is why char += char can pass the code check while char = (char+char) considered char = int?
C# Specification, Section 7.17.2 Compound assignment:
An operation of the form x op= y is processed by applying binary operator overload resolution (§7.3.4) as if the operation was written x op y. Then,
...
• Otherwise, if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type of x, and if y is implicitly convertible to the type of x or the operator is a shift operator, then the operation is evaluated as x = (T)(x op y), where T is the type of x, except that x is evaluated only once
And that's exactly the situation we have here. The return type of the operation is int but the types of x and y are both char, and so an extra cast is automatically inserted for us.
(I believe this rule exists because there's nowhere for you to be able to insert an explicit cast yourself and it's kind of "expected" to work, especially in cases where x and y are the same type)
In the second case it is the assignment that is failing, not the calculation itself. If you explicitly cast the result in the second line to a char it works fine and indeed the following three lines generate identical IL:
c += (char)1;
c = (char)(c + (char)1);
c = (char)(c + 1);
So yes. There is a difference.
Note in the third line I didn't bother casting the 1 to char since the calculation will just convert it back to an int anyway.
The resulting type of += is char in this case and the resulting type of c + (char)1 is int.
The following code prints:
o1 System.Char o2 System.Int32
public static void Main(string[] args)
{
char c = 'a';
object o1 = c += (char)1;
object o2 = c + (char)1;
WriteLine("o1 " + o1.GetType());
WriteLine("o2 " + o2.GetType());
}
To put Damien's answer in simpler terms:Compound operators (e.g. +=, -= etc.) automatically cast the result to the targeted type (if possible).
Therefore c += 'a' works, because it is evaluated as c = (char)(c + 'a').
In this case, the conversion is necessary, because the return-type of arithmetic operations between chars is int (which is why c = c + 'a' does not compile, as it is missing the cast above).

What's the correct way to implement operator ++ for value-types?

I'm working on a custom implementation of a Number struct, with very different ways of storing and manipulating numeric values.
The struct is fully immutable - all fields are implemented as readonly
I'm trying to implement the ++ and -- operators, and I've run into a little confusion:
How do you perform the assignment?
Or does the platform handle this automatically, and I just need to return n + 1?
public struct Number
{
// ...
// ... readonly fields and properties ...
// ... other implementations ...
// ...
// Empty placeholder + operator, since the actual method of addition is not important.
public static Number operator +(Number n, int value)
{
// Perform addition and return sum
// The Number struct is immutable, so this technically returns a new Number value.
}
// ERROR here: "ref and out are not valid in this context"
public static Number operator ++(ref Number n)
{
// ref seems to be required,
// otherwise this assignment doesn't affect the original variable?
n = n + 1;
return n;
}
}
EDIT: I think this is not a duplicate of other questions about increment and decrement operators, since this involves value-types which behave differently than classes in this context. I understand similar rules apply regarding ++ and --, but I believe the context of this question is different enough, and nuanced enough, to stand on its own.
The struct is fully immutable - all fields are implemented as readonly
Good!
I'm trying to implement the ++ and -- operators, and I've run into a little confusion: How do you perform the assignment?
You don't. Remember what the ++ operator does. Whether it is prefix or postfix it:
fetches the original value of the operand
computes the value of the successor
stores the successor
produces either the original value or the successor
The only part of that process that the C# compiler does not know how to do for your type is "compute the successor", so that's what your overridden ++ operator should do. Just return the successor; let the compiler deal with figuring out how to make the assignment.
Or does the platform handle this automatically, and I just need to return n + 1?
Yes, do that.
The processing of ++ and -- operators is described in C# language specification, section 7.7.5 Prefix increment and decrement operators:
The run-time processing of a prefix increment or decrement operation of the form ++x or --x consists of the following steps:
• If x is classified as a variable:
  o x is evaluated to produce the variable.
  o The selected operator is invoked with the value of x as its argument.
  o The value returned by the operator is stored in the location given by the evaluation of x.
  o The value returned by the operator becomes the result of the operation.
So a custom overloads of these operators only need to produce an incremented/decremented value. The rest is handled by the compiler.
A Number class is going to have a value of some kind as a property.
public static Number operator ++(Number n)
{
// ref seems to be required,
// otherwise this assignment doesn't affect the original variable?
n.value = n.value + 1;
return n;
}
This should do what you want.
I wrote this using your struc and added the value property.
private static void Main(string[] args)
{
var x = new Number();
x.value = 3;
x++;
Console.WriteLine(x.value);
Console.Read();
}
This properly generates a 4
The statement num++; by itself expands to num = PlusPlusOperator(num);. Since your data type is immutable, just return n+1; and the compiler will handle the rest.

defining operator + , = and +=

I once read the following statement from a C++ notes,
In C++, defining operator + and = does not give the right meaning to +=. This language-design bug is fixed in C#
I would like to know what exactly does this statement want to say? Is that related to operator overload?
I prefer C++ operator overloading mechanism. It definitely not a design bug according to me.
+, = and += are three different operators. If you want to use += you need to overload +=. Overloading + and = won't make += work.
I would like to add that in E1 += E2 E1 gets evaluated only once as far as C++ is concerned. I don't know the exact rules in C#.
It says, that in C# if you have overloaded operator + C# automatically will emulate operator += as combination of + and = (a=a+b is equal to a+=b). In C++ it's not implemented, but it's not a bug. In C++ + and = doesn't give you += because mostly += works faster than +, because there is no need to create one more object.
That's why mostly operator + is writen using += operator. Consider fallowing code:
class foo
{
public:
foo& operator+=(const foo& rhs)
{
//.......
}
};
const foo operator+(const foo& lhs,const foo& rhs)
{
foo temp = lhs;
return temp+= rhs;
}
It means that in C++ if you defined your own operator + and operator = for your class, that still does not mean that your class will automatically support the += operator. If you want the += operator to work for your class, you have to define the += explicitly and separately.
In C#, if I understood it correctly, defining operators + and = for your class will also mean that you'll be able to use operator += with your class. The += will be "emulated" through combination of operator + and operator =. E.g. expression a += b will be interpreted as a = a + b.
It doesn't work that way in C++. If you don't define the += explicitly, a += b will result in compiler error, even if you have + and = defined.
C# does not allow operator overloading = since it does not allow direct pointer management. Its behavior is fixed based on whether it is reference or value type. For the same reason you cannot overload += . It's meaning will always be doing the sum and assignment. You can only therefore decide what the meaning for + is to your datastructure.

Categories

Resources