Does the ternary "?: operator" have a bug in C#? - 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;
}

Related

In C#, I would love to define the > and < operators for string [duplicate]

This question already has answers here:
C# String Operator Overloading
(7 answers)
Closed 1 year ago.
Personally, I find the string.CompareTo() annoying to use and read.
I would love to read and write like: if (string1 > string2)
Currently, I can do this, using ExtensionMethods:
string a = "ABC";
string b = "BBC";
if ( a.IsGreaterThan(b) )
{
Console.WriteLine("a is greater than b");
}
else if ( a.IsLessThan(b) )
{
Console.WriteLine("a is less than b");
}
public static class StringExtensions
{
public static bool IsGreaterThan(this string i, string value)
{
return (i.CompareTo(value) > 0);
}
public static bool IsLessThan(this string i, string value)
{
return (i.CompareTo(value) < 0);
}
}
This is much better, but I'd still like to define the < and > operators. I found an OLD post explaining why this is NOT possible:
Currently this is not supported because Extension methods are defined in separate static class and static classes cannot have operator overloading definitions.
Has anything changed in C# to now allow defining the < and > operators for string class?
I'd still like to define the < and > operators
But why [.gifv]?
What does it mean to you that a string is "greater than" another? Its length? Or the first Unicode codepoint within it that's higher than the codepoint at the same location in the first string?
What about combined characters? Is ñ (U+00F1) greater or smaller than n and ~ combined (U+006E and U+0303), or perhaps equal? What about i + j and ij? Would the current culture matter?
Be happy that there's such a "clumsy" method to do comparisons, so you can call an overload on it to specify what kind of comparison you actually want. There is no one size fits all in string comparisons, and you definitely shouldn't be able to override it for all strings.
Besides, already compiled code doesn't care about extension methods (or extension operators, if that were a thing). Consider you're running library code in which you can definitely read that there's a if (foo < bar) and in your code it's true, but in the compiled code it's false, because it does a different comparison for the same operator.
So no, C# doesn't allow overriding operators for built-in types.

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

can I do an assignment in C# with a shorter conditional statement

I would like to know if there is simpler way to check a condition and assign the same variable if the condition is false similar to null-coalescing operator (??)
Here is how it can be done now
int i = 0;
...
int j = (i == 0) ? 1 : i;
Can it be made simpler like
int i = 0
...
int j = (i == 0) ?? 1;
I understand it won't work that way since ?? only checks for null. But I'm wondering if it can achieved with a different operator.
You could create an extension method for int types that will do what you want:
public static class Extensions
{
public static int IfZero (this int value, int defaultValue)
{
return value == 0 ? defaultValue : value;
}
public static int ReplaceValue(this int value, int valueToReplace, int replaceWith)
{
return value == valueToReplace ? replaceWith : value;
}
}
Then it could be used throughout your program like:
int i = 0;
int j = i.IfZero(1);
// Or using the more generic method:
int j = i.ReplaceValue(0, 1);
I think what you're looking for is impossible in general (as opposed to when more info is available as I mention below). The reason is that you need 3 pieces of information for the job:
the value to check for
the value to use if true
the value to use if false
The ?? operator gets around that by assuming that 1 is null. But that would mean that you would need a separate operator for every value of 1 that you would want to test for. This is worthwhile for the C# team to write for something as common as null. Not for most things. (Of courses you could write your own for cases you know you need. But it seems like you're looking for something built in.)
In your specific case
Assuming that the minimum has to be 1, you can have:
j = Math.Max(1, i);
In response to those asking why would the OP be looking for simpler code than already very simple code, this might be to reflect the logic behind the action, and therefore be (in a sense) more readable.
No, the language does not offer that.
You can write a generic extension method, though:
public static class CoalescingExtensions
{
public static T IfDefault<T> (this T value, T valueIfDefault)
{
return value.Equals(default(T)) ? valueIfDefault: value;
}
}
The code is using 0 to determine whether or not the variable has been initialized. However, this can create issues since 0 is a valid value for an integer.
If checking for a different default value is acceptable, try using nullable types. This will allow you to use the null coalescing operator.
int? i = null;
...
int j = i?? 1;
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/nullable-types/

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.

Compiler generated overloads for comparison operators

If there are operator overloads for <, > and ==, shouldn't the compiler be able to create for <= and >= automatically?
(a <= b) means (a < b || or a == b)
(a >= b) means (a > b || or a == b)
At least, the compiler does the same for += if + is overloaded.
+= and >= are not the same from functional point of view.
u+=2 is a short hand operand over u=u+2
>= is short hand for > || ==.
So you have 2 consecutive calls in second case MoreThan() || Equal(), which may provide problems like
short circuits
stack overflow
return type of that functons may not be bool at all (as mantioned by #vcjones)
...
But in general: aggregate automaticaly (under the hood) user defined functions is never a good idea as a final result is not stable, as depends on concrete implementation, so unpredictable. And you don't want your compiler to generate unpredictable code.
No, it cannot. One reason being that operators don't have to return a bool (though I don't know why anyone would do this). For example:
public static string operator <(Class1 a, Class1 b)
{
return "hello";
}
public static int operator >(Class1 a, Class1 b)
{
return "bye";
}
This compiles fine, and in this scenario the compiler can't really make the other operator automatically. How should the compiler decide what the opposite value of a string is?

Categories

Resources