C# What does int i = +1 mean? - c#

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

Related

Change this condition so that it does not always evaluate to 'true'

Why is SonarQube complaining about this part of the code?
I checked this code and not always this value is true.
public static void WriteJson(object value)
{
decimal decimalValue = ((decimal?)value).Value;
int intValue = (int)decimalValue;
if (decimalValue == intValue)
Console.WriteLine(intValue);
else
Console.WriteLine(decimalValue);
Console.ReadKey();
}
Why is SonarQube complaining about this?
The false positive is related to an imperfection in our dataflow analysis engine - it does not take into account the casts between floating point and integer numbers (yet) and cannot recognize when a floating point number has been truncated.
I will try to elaborate a bit: the dataflow analysis engine tracks the values of the local variables in the analyzed methods, and when a new value is being assigned to a variable, the engine creates a special object that represents the actual value. When you assign one variable to another variable, that object remains the same. For example:
var x = 5; // the symbol of x is associated with value_0
var y = x; // the symbol of y is associated with value_0
if (x == y) // value_0 is compared with value_0 --> always true
The values we assign do not contain type information (yet) and we cannot detect (yet) changes in cases like yours:
var x = 5.5; // the symbol of x is associated with value_0
var y = (int)x; // the symbol of y is associated with value_0 (wrong)
if (x == y) // false positive
and we generate false positives, but they are relatively rare, because most casts do not generate new values.
Thanks for the feedback, we will be looking into that in the near future.
Looks like SonarQube detects that you are assigning the same value to both variables, assume that value passed to method is equal to 2
1. decimal decimalValue = 2
2. int intValue = (int)decimalValue;
therefore decimalValue = 2 and intValue = 2
The C# compiler will obviously cast it to int so in case you pass 2.5 the if comparision will not evaluate always to true. But most probably SonarQube is just not aware about the casting. So it assumes always true.
I am not an expert at SonarQube, but I guess it is because SonarQube detects that you are setting intValue to the rounded form of decimalValue. And then again you are comparing decimalValue to the decimal form of intValue. So, in many cases, it will return 'true'.
To see how it will play out, suppose the decimalValue is "123.0". Then, the intValue will be exactly "123". Then, we compare "123.0"(The value of decimalValue) to "123.0"(The value of intValue after converting to decimal) with an "if" statement, which will return true. This will play out for all integers.

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.

Does the ternary "?: operator" have a bug in C#?

Why can not I run the following code ?
static int num = 0;
static void Main(string[] args)
{
(num == 0) ? inc() : dec();
}
public static void inc()
{
num++;
}
public static void dec()
{
num--;
}
Why doesn't C# allow me to use the ternary "?:" operator to check a condition and then run a method accordingly without the need to return any value? Equivalently to this:
if (num == 0) inc();
else dec();
I am not sure if the same rule is applied in other languages, e.g., Java, C++, etc...
why can not I run the following code ?
Because you're trying to violate the language specification. The operands of the conditional operator (section 7.14 in the C# 4 spec) have to be expressions - and an invocation of a method with a return type of void is explicitly "only valid in the context of a statement-expression" (see section 7.1 of the C# 4 spec).
The purpose of the conditional operator is to provide an expression which is the result of evaluating one of two expressions based on a condition. It's not to execute one of two actions based on a condition. Just use an if statement.
Likewise the conditional operator does not form a valid statement on its own, any more than various other operators do:
a + b; // Invalid
x = a + b; // Valid, assignment expression can be an expression-statement
Explicitly from section 8.6 of the spec:
Not all expressions are permitted as statements. In particular, expressions such as x + y and x == 1 that merely compute a value (which will be discarded) are not permitted as statements.
Jon Skeet's answer is perfectly documenting that C# intentionally went a different route than C++. It is difficult to say why, but I will try because I believe that that question deserves an answer, too.
C# shares a lot of syntax with C++ and with Java. In this case, the Java way was chosen. This concerns both the inability to write 2 + 2; as a standalone statement, as well as requiring that ternary operator returns a value.
I believe that both of these decisions have a lot to do with elimination of inaccessible code. The + operator in 2 + 2 can be optimized away and therefore if it serves any purpose in the code, that purpose is unreliably served! Static analysis (compilation error or warning) should ideally tell you that there seems to be a semantic problem in such a case and force you to delete or rewrite the inaccessible code.
So, expressions are no longer always statements, and the C grammar needs to be redefined for Java/C#, with expressions always returning values and statements never returning values.
Now ?: and if-else differ primarily in one being an expression and one being a statement, at least in their typical uses. So the redefined grammar simply chose to ban void ternaries and recommend if-else for that purpose.
Because Ternary operator assigns value based on a boolean expression. Its basic C# spec. If your methods are void return type then best is to use if - else or switch case.
int a = true ? 0 : 1; //Always works
true ? 0 : 1; //This will never work.
Or you example modified a little.
static int num = 0;
static void Main(string[] args)
{
num = (num == 0) ? inc(num) : dec(num);
}
public static int inc(int lnum)
{
return lnum + 1;
}
public static int dec(int lnum)
{
return lnum - 1;
}
The conditional operator (?:) returns one of two values depending on the value of a Boolean expression.
It does not act the way you have described in your question.
Here are more bytes on the ternary operator
http://msdn.microsoft.com/en-us/library/ty67wk28%28v=vs.80%29.aspx
But it will work when used this way:
static int num = 0;
static void Main(string[] args)
{
num = (num == 0) ? inc(num) : dec(num);
}
public static int inc(int number)
{
return number + 1;
}
public static int dec(int number)
{
return number - 1;
}

unchecked block doesn't work with BigInteger?

Just noticed that the unchecked context doesn't work when working with a BigInteger, for instance:
unchecked
{
// no exception, long1 assigned to -1 as expected
var long1 = (long)ulong.Parse(ulong.MaxValue.ToString());
}
unchecked
{
var bigInt = BigInteger.Parse(ulong.MaxValue.ToString());
// throws overflow exception
var long2 = (long)bigInt;
}
Any idea why that's the case? Is there something special with the way big integers are converted to other primitive integer types?
Thanks,
The C# compiler has no idea whatsoever that a BigInteger is logically an "integral type". It just sees a user-defined type with a user-defined explicit conversion to long. From the compiler's point of view,
long long2 = (long)bigInt;
is exactly the same as:
long long2 = someObject.SomeMethodWithAFunnyNameThatReturnsALong();
It has no ability to reach inside that method and tell it to stop throwing exceptions.
But when the compiler sees
int x = (int) someLong;
the compiler is generating the code doing the conversion, so it can choose to generate checked or unchecked code as it sees fit.
Remember, "checked" and "unchecked" have no effect at runtime; it's not like the CLR goes into "unchecked mode" when control enters an unchecked context. "checked" and "unchecked" are instructions to the compiler about what sort of code to generate inside the block. They only have an effect at compile time, and the compilation of the BigInt conversion to long has already happened. Its behaviour is fixed.
The OverflowException is actually being thrown by the explicit cast operator defined on BigInteger. It looks like this:
int num = BigInteger.Length(value._bits);
if (num > 2)
{
throw new OverflowException(SR.GetString("Overflow_Int64"));
}
In other words, it handles overflows this way regardless of the checked or unchecked context. The docs actually say so.
Update: Of course, Eric is the final word on this. Please go read his post :)
The documentation explicitly states that it will throw OverflowException in this situation. The checked context only makes a difference to "native" arithmetic operations that the C# compiler emits - which doesn't include invoking explicit conversion operators.
To perform the conversion "safely" you'd have to compare it with long.MaxValue and long.MinValue first to check whether or not it's in range. To get the overflow-to-negative effect, I suspect you'd have to perform use bitwise operators within BigInteger first. For example:
using System;
using System.Numerics;
class Program
{
static void Main(string[] args)
{
BigInteger bigValue = new BigInteger(ulong.MaxValue);
long x = ConvertToInt64Unchecked(bigValue);
Console.WriteLine(x);
}
private static readonly BigInteger MaxUInt64AsBigInteger
= ulong.MaxValue;
private static long ConvertToInt64Unchecked(BigInteger input)
{
unchecked
{
return (long) (ulong) (input & MaxUInt64AsBigInteger);
}
}
}

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

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.

Categories

Resources