Related
The Documentation implies that out parameters do not need to be initialized (only declared) before they are sent to the function. However, this code:
class Program
{
static void Main()
{
dynamic p = "";
string s;
if (p != null && T(out s))
System.Console.WriteLine(s);
}
static bool T(out string s)
{
s = "";
return true;
}
}
Gives the build error:
Use of unassigned local variable 's'
only when p is dynamic. If p is typed as string or object, no error is produced.
Method T is required to set the variables before returning, so this error seems like hogwash to me (Note that even with a short-circuting &&, the second statement has to execute in order for the "then" block to execute).
Note: you can also download this repro repo to reproduce.
So, is this a legitimate bug (I'm on C# 7.0)? How should I handle this?
UPDATE: This question was the subject of my blog in November 2018. Thanks for the interesting question!
The documentation implies that out parameters do not need to be initialized (only declared) before they are sent to the method.
That's correct. Moreover, a variable passed to an out parameter is definitely assigned when the call returns, because as you note:
Method T is required to set the variables before returning, so this error seems like hogwash to me
Seems that way, doesn't it? Appearances can be deceiving!
Note that even with a short-circuiting &&, the second expression has to execute in order for the "consequence" block of the if to execute.
That is, surprisingly, false. There is a way for the consequence to execute even if the call to T does not execute. Doing so requires us to seriously abuse the rules of C#, but we can, so let's do it!
Instead of
dynamic p = "";
string s;
if (p != null && T(out s))
System.Console.WriteLine(s);
We'll do
P p = new P();
if (p != null && T())
System.Console.WriteLine("in the consequence");
and give a definition for class P that causes this program to run the consequence but not run the call to T.
The first thing we have to do is turn p != null into a method call instead of a null check, and that method must not return bool:
class P
{
public static C operator ==(P p1, P p2)
{
System.Console.WriteLine("P ==");
return new C();
}
public static C operator !=(P p1, P p2)
{
System.Console.WriteLine("P !=");
return new C();
}
}
We are required to overload both == and != at the same time in C#. Overriding Equals and GetHashCode is a good idea but not a requirement, and nothing in this program is a good idea so we'll skip that.
OK, so we now have if (something_of_type_C && T()), and since C is not bool, we'll need to override the && operator. But C# does not allow you to override the && operator directly. Let's digress a moment and talk about the semantics of &&. For Boolean-returning functions A and B, the semantics of bool result = A() && B(); are:
bool a = A();
bool c;
if (a == false) // interesting operation
c = a;
else
{
bool b = B();
c = a & b; // interesting operation
}
bool r = c;
So we generate three temporaries, a, b, and c, we evaluate the left side A(), we check to see if a is false. If it is, we use its value. If not, we compute B() and then compute a & b.
The only two operations in that workflow that are specific to the type bool are check for falsity and non-short-circuiting &, so *those are the operations that are overloaded in a user-defined &&. C# requires you to overload three operations: user defined &, user defined "am I true?" and user defined "am I false?". (Like == and !=, the last two have to be defined in pairs.)
Now, a sensible person would write operator true and operator false so that they always returned opposites. We are not sensible people today:
class C
{
public static bool operator true(C c)
{
System.Console.WriteLine("C operator true");
return true;
}
public static bool operator false(C c)
{
System.Console.WriteLine("C operator false");
return true; // Oops
}
public static C operator &(C a, C b)
{
System.Console.WriteLine("C operator &");
return a;
}
}
Notice that we also require that user-defined & take two Cs and return a C, which it does.
All right, so, recall we had
if (p != null && T())
and p != null is of type C. So we must now generate this as:
C a = p != null; // Call to P.operator_!=
C c;
bool is_false = a is logically false; // call to C.operator_false
if (is_false)
c = a;
else
{
bool b = T();
c = a & b; // Call to C.operator_&
}
But now we have a problem. operator & takes two Cs and returns a C, but we have a bool returned from T. We need a C. No problem, we'll add an implicit user-defined conversion to C from bool:
public static implicit operator C(bool b)
{
System.Console.WriteLine("C implicit conversion from bool");
return new C();
}
OK, so our logic is now:
C a = p != null; // Call to P.operator_!=
C c;
bool is_false = C.operator_false(a);
if (is_false)
c = a;
else
{
bool t = T();
C b = t; // call to C.operator_implicit_C(bool)
c = a & b; // Call to C.operator_&
}
Remember what we are heading towards here is:
if (c)
System.Console.WriteLine("in the consequence");
How do we compute this? C# reasons that if you have operator true on C then you should be able to use it in an if condition by simply calling operator true. So finishing it off, ultimately we have the semantics:
C a = p != null; // Call to P.operator_!=
C c;
bool is_false = C.operator_false(a);
if (is_false)
c = a;
else
{
bool t = T();
C b = t; // call to C.operator_implicit_C(bool)
c = a & b; // Call to C.operator_&
}
bool is_true = C.operator_true(c);
if (is_true) …
But as we see in this crazy example, we can enter the consequence of the if without calling T no problem provided that operator false and operator true both return true. When we run the program we get:
P !=
C operator false
C operator true
in the consequence
A sensible person would never write code where a C was considered to be both true and false at the same time, but a not-sensible person like me today could, and the compiler knows that because we designed the compiler to be correct regardless of whether the program is sensible.
So that explains why if (p != null && T(out s)) says that s can be unassigned in the consequence. If p is dynamic then the compiler reasons "p might be one of these crazy types at runtime, in which case we are no longer working with bool operands, and therefore s might not be assigned".
The moral of the story is: dynamic makes the compiler extremely conservative about what could happen; it has to assume the worst. In this particular case, it has to assume that p != null might not be a null reference check and might not be bool, and that operator true and operator false might both return true.
So, is this a legitimate bug (I'm on C# 7.0)?
The compiler's analysis is correct -- and believe me, this was not easy logic to write or test.
Your code has the bug; fix it.
How should I handle this?
If you want to do a null reference check against a dynamic, your best bet is: if it hurts when you do that, don't do that.
Cast away the dynamic and get back to object, and then do the reference equality check: if (((object)p) == null && …
Or, another nice solution is to make it extremely explicit:
if (object.ReferenceEquals((object)p, null) && …
Those are my preferred solutions. A worse solution is to break it up:
if (p != null)
if (T(out string s))
consequence
Now there is no operator & called even in the worst case. Note though in this case we can still be in a scenario where p != null is true and p is null, since there is nothing stopping anyone from overloading != to always return true regardless of its operands.
I am using a 3rd party tool (Unity3d), where one of the fundamental base classes overloads the == operator (UnityEngine.Object).
The overloaded operator's signature is:
public static bool operator == (UnityEngine.Object x, UnityEngine.Object y)
Does the order in which the comparison is made have any effect on whether this overloaded operator is used ?
To illustrate, should both of these use the overloaded operator and return the same result ?
// initialize with some value
UnityEngine.Object a = ....
Debug.Log(a == null);
Debug.Log(null == a);
The reason i'm asking is because i'd like to (sometimes) avoid this overloaded behaviour (use the default == operator), and was wondering whether flipping the order would assist in that ?
(There could be another option - casting the operands to System.object, but I am not 100% sure that works).
Well, it's possible that the two calls wouldn't be the same, if the operator had been overloaded badly. Either there could be one overload, and it could be written in a way which compares the operands asymmetrically, or the two statements could call different overloads.
But assuming it's been overloaded properly, that should be absolutely fine. That's if you want to call the overloaded operator, of course. In situations where you don't, I'd make that clear using ReferenceEquals.
I would personally recommend the if (a == null) approach, as I find it easier to read (and I believe many others do too). The "yoda" style of if (null == a) is sometimes used by C programmers who fear typos, where if (a = null) would be an assignment and a valid statement... albeit with a warning in decent C compilers.
Here's an example of a badly implemented set of overloads, where the operand order matters, because null is convertible to both string and Test:
using System;
class Test
{
public static bool operator ==(Test t, string x)
{
Console.WriteLine("Test == string");
return false;
}
public static bool operator !=(Test t, string x)
{
Console.WriteLine("Test != string");
return false;
}
public static bool operator ==(string x, Test t)
{
Console.WriteLine("string == Test");
return false;
}
public static bool operator !=(string x, Test t)
{
Console.WriteLine("string != Test");
return false;
}
static void Main(string[] args)
{
Test t = null;
Console.WriteLine(t == null);
Console.WriteLine(null == t);
}
}
Now that the question has been updated, we can tell that's not the case... but the implementation could still be poor. For example, it could be written as:
public static bool operator == (UnityEngine.Object x, UnityEngine.Object y)
{
// Awful implementation - do not use!
return x.Equals(y);
}
In that case, it will fail with a NullReferenceException when x is null, but succeed if x is non-null but y is null (assuming Equals has been written properly).
Again though, I'd expect that the operator has been written properly, and that this isn't a problem.
UPDATE after updating the question:
If you want to avoid calling the overloaded function when comparing to null, use ReferenceEquals:
if(a.ReferenceEquals(null)) ...
OLDER ANSWER, RENDERED OBSOLETE AND ALSO WRONG BY #Jon Skeet...
According to this, overload resolution of binary operator with X and Y as arguments is done by first taking the union of all operators defined by X and by Y.
So a==b results in exactly the same overload resolution as b==a.
The link is from 2003, but I doubt Microsoft has changed something since, it would have broken a lot of older code.
Update: Although I witnessed this behaviour in prior versions of Unity, I couldn't reproduce it in a test I performed right after writing this answer. May be Unity changed the == operator behaviour, or behaviour of implicit conversion of UnityEngine.Object to bool; however, I would still advocate using the overridden == operator instead of trying to avoid it.
The way Unity in particular overrides == operator is very frustrating, but also fundamental for how you have to work with the engine. After the UnityObject gets destroyed, by calling Destroy (some time after the call) or DestroyImmediate (immediately after the call, as the name would suggest), the comparison of this object to null returns true, even though it's not a null reference.
It's completely unintuitive for C# programmers, and can create a lot of truly WTF moments before you figure this out. Take this, for example:
DestroyImmediately(someObject);
if (someObject)
{
Debug.Log("This gets printed");
}
if (someObject != null)
{
Debug.Log("This doesn't");
}
The reason I'm explaining that is because I perfectly understand your desire to avoid this strange overridden behaviour, especially if you had C# experience before working with Unity. However, as with a lot of other Unity-specific stuff, it might actually be better to just stick to the Unity convention instead of trying to implement everything in the C#-correct way.
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;
}
Suppose you are using the ternary operator, or the null coalescing operator, or nested if-else statements to choose assignment to an object. Now suppose that within the conditional statement, you have the evaluation of an expensive or volatile operation, requiring that you put the result into a temporary variable, capturing its state, so that it can be compared, and then potentially assigned.
How would a language, such as C#, for consideration, implement a new logic operator to handle this case? Should it? Are there existing ways to handle this case in C#? Other languages?
Some cases of reducing the verbosity of a ternary or null coalescing operator have been overcome, when we assume that we are looking for direct comparisons, for example. See Unique ways to use the Null Coalescing operator, in particular the discussion around how one can extend the usage of the operator to support String.IsNullOrEmpty(string). Note how Jon Skeet is using the PartialComparer from MiscUtil, to reformat 0s to nulls,
Why is this possibly necessary? Well, take a look at how we write a comparison method for complex objects without any shortcuts (examples from the cited discussions):
public static int Compare( Person p1, Person p2 )
{
return ( (result = Compare( p1.Age, p2.Age )) != 0 ) ? result
: ( (result = Compare( p1.Name, p2.Name )) != 0 ) ? result
: Compare( p1.Salary, p2.Salary );
}
Jon Skeet writes a new comparison to fallback the equality case. This allows the expression to extend by writing a new specific method which returns null, allowing us to use the null coalescing operator:
return PartialComparer.Compare(p1.Age, p2.Age)
?? PartialComparer.Compare(p1.Name, p2.Name)
?? PartialComparer.Compare(p1.Salary, p2.Salary)
?? 0;
The null coalescing operator is more readable because it has two sides, not three. The boolean condition clause is separated into a method, in this case returning null if the expression must be continued.
What would the above expression look like if we could more easily put the condition in-line? Take the expression from PartialComparer.Compare which returns null, and place it in a new ternary expression which allows us to use the evaluation of the left-side expression, with an implicit temporary variable value:
return Compare( p1.Age, p2.Age ) unless value == 0
: Compare( p1.Name, p2.Name ) unless value == 0
: Compare( p1.Salary, p2.Salary );
The basic "flow" of an expression would be:
expression A unless boolean B in which case expression C
Rather than being an overloaded comparison operator, I suppose this is more like a short-circuiting inverted ternary operator.
Would this type of logic be useful? Currently the null coalescing provides us a way to do this with the conditional expression (value == null).
What other expressions would you want to test against? We've heard of (String.IsNullOrEmpty(value)).
What would be the best way to express this in the language, in terms of operators, keywords?
personally I'd avoid the short circuit from operators and just let the methods chain it:
public static int CompareChain<T>(this int previous, T a, T b)
{
if (previous != 0)
return previous;
return Comparer<T>.Default.Compare(a,b);
}
use like so:
int a = 0, b = 2;
string x = "foo", y = "bar";
return a.Compare(b).CompareChain(x,y);
can be inlined by the JIT so it can perform just as well as short circuiting built into the language without messing about with more complexity.
In response to your asking whether the above 'structure' can apply to more than just comparisons then yes it can, by making the choice of whether to continue or not explict and controllable by the user. This is inherently more complex but, the operation is more flexible so this is unavoidable.
public static T ElseIf<T>(
this T previous,
Func<T,bool> isOK
Func<T> candidate)
{
if (previous != null && isOK(previous))
return previous;
return candidate();
}
then use like so
Connection bestConnection = server1.GetConnection()
.ElseIf(IsOk, server2.GetConnection)
.ElseIf(IsOk, server3.GetConnection)
.ElseIf(IsOk, () => null);
This is maximum flexibility in that you can alter the IsOk check at any stage and are entirely lazy. For situations where the is OK check is the same in every case you can simplify like so and entirely avoid extensions methods.
public static T ElseIf<T>(
Func<T,bool> isOK
IEnumerable<Func<T>[] candidates)
{
foreach (var candidate in candidates)
{
var t = candidate();
if (isOK(t))
return t;
}
throw new ArgumentException("none were acceptable");
}
You could do this with linq but this way gives a nice error message and allows this
public static T ElseIf<T>(
Func<T,bool> isOK
params Func<T>[] candidates)
{
return ElseIf<T>(isOK, (IEnumerable<Func<T>>)candidates);
}
style which leads to nice readable code like so:
var bestConnection = ElseIf(IsOk,
server1.GetConnection,
server2.GetConnection,
server3.GetConnection);
If you want to allow a default value then:
public static T ElseIfOrDefault<T>(
Func<T,bool> isOK
IEnumerable<Func<T>>[] candidates)
{
foreach (var candidate in candidates)
{
var t = candidate();
if (isOK(t))
return t;
}
return default(T);
}
Obviously all the above can very easily be written using lambdas so your specific example would be:
var bestConnection = ElseIfOrDefault(
c => c != null && !(c.IsBusy || c.IsFull),
server1.GetConnection,
server2.GetConnection,
server3.GetConnection);
You've got lots of good answers to this question already, and I am late to this particular party. However I think it is worthwhile to note that your proposal is a special case of a more generally useful operation which I dearly wish C# had, namely, the ability to in an expression context, give a name to a temporary computation.
In fact C# has this operator but only in query comprehensions. I wish we had been able to add this as an operator in C# 3:
public static int Compare(Person p1, Person p2) =>
let ages = Compare(p1.Age, p2.Age) in
ages != 0 ?
ages :
let names = Compare(p1.Name, p2.Name) in
names != 0 ?
names :
Compare(p1.Salary, p2.Salary);
"Let expressions" are one of those expressions that are so useful, and found in so few languages, and I genuinely do not understand why language designers do not add it immediately in version one.
If C# had this feature then your proposed:
A() unless B() : C()
is simply
let a = A() in B() ? C() : a
which is hardly more difficult to understand, and bonus, you get to use a in expressions B() and C() if you like.
Let expressions can be emulated in any language that has lambdas; of course let x = y in z is simply (x=>z)(y), but there is no concise way to write that in C# either because C# requires a conversion to a delegate type on every lambda.
Incidentally, in Roslyn we do not represent temporaries as let-expressions, though we could. Rather, we go even one level below that and have a representation for "sequence of operations that might produce values, one of which will become the value of this expression". "let x = y in z" is simply the sequence "allocate x, x = y, z, deallocate x" where the third element is the value. And in the original pre-roslyn C# compiler we had internal operators "left" and "right", which were binary operators that took two expressions and produced either the left or right side, so we could generate ((allocate x) right ((x = y) right z)) left (deallocate x).
My point here is: we often get requests for bespoke language features with unusual punctuation, but it would in general have been better to implement the basic building blocks that you could build these operators out of in a natural way.
To place one proposed implementation away from a very verbose question, let's run with the unless keyword.
(expression A) unless (boolean B) <magical "in which case" operator> (expression C)
... would be all there is to it.
Boolean expression B would have access to the evaluation of expression A through the keyword value. Expression C could have the unless keyword in its expression, allowing for simple, linear chaining.
Candidates for the <magical "in which case" operator>:
:
|
?:
otherwise keyword
Usage of any symbols tend to diminish readability for the average developer. Even the ?? operator is not used widely. I, myself, do prefer to develop verbose code, but that I can easily read one year from now.
So a candidate for your :
expression A unless boolean B in which case expression C.
would be
expression A unless boolean B sothen expression C.
Although many people like me would still use:
if (B) {expression C;}
else {expression A;}
This comes in when you are developing a software with a big team, with different backgrounds, each one on the team master of one language, and just user of others.
More #ShuggyCoUk: Ah, I see that this might work for more than just comparisons? I haven't used C# 3 and extension methods, but I suppose you can declare, for my previous example, below, a
public delegate bool Validation<T>( T toTest );
public static T Validate<T>( this T leftside, Validation<T> validator )
{
return validator(leftside) ? leftside : null;
}
Followed by, per Skeet:
Validation<Connection> v = ( Connection c ) => ( c != null && !( c.IsBusy || c. IsFull ) );
Connection bestConnection =
server1.GetConnection().Validate( v ) ??
server2.GetConnection().Validate( v ) ??
server3.GetConnection().Validate( v ) ?? null;
Is this how that would work in C#? Comments appreciated. Thank you.
In response to ShuggyCoUk:
So this is an extension method in C# 3, then? Also, the result here is an int, not an arbitrary expression. Useful for overloading yet another comparison method. Suppose I wanted an expression for choosing the best connection. Ideally, I want something to simplify the following:
Connection temp;
Connection bestConnection =
( temp = server1.GetConnection() ) != null && !(temp.IsBusy || temp.IsFull) ? temp
: ( temp = server2.GetConnection() ) != null && !(temp.IsBusy || temp.IsFull ) ? temp
: ( temp = server3.GetConnection() ) != null && !(temp.IsBusy || temp.IsFull ) ? temp
: null;
Ok, so one could have a method
bool IsOk( Connection c )
{
return ( c != null && !(c.IsBusy || c.IsFull) );
}
Which would produce:
Connection temp;
Connection bestConnection =
( temp = server1.GetConnection() ) && IsOk( temp ) ? temp
: ( temp = server2.GetConnection() ) && IsOk( temp ) ? temp
: ( temp = server3.GetConnection() ) && IsOk( temp ) ? temp
: null;
But how would method chaining for comparisons work, here? I am pondering something which looks like:
Connection bestConnection =
server1.GetConnection() unless !IsOk(value) otherwise
server2.GetConnection() unless !IsOk(value) otherwise
server3.GetConnection() unless !IsOk(value) otherwise null;
I think that there are so far, hoops to jump through, if I want the result of a conditional to be an expression or result of a method which was in the original conditional.
I assume that the object returned by such methods will be expensive to produce, or will change the next time the method is called.
Overloading the comparison operator, how to compare if the two variables points to the same object(i.e. not value)
public static bool operator ==(Landscape a, Landscape b)
{
return a.Width == b.Width && a.Height == b.Height;
}
public static bool operator !=(Landscape a, Landscape b)
{
return !(a.Width == b.Width && a.Height == b.Height);
}
Use the Object.ReferenceEquals static method.
Of course, in order for the == and != method to retain their full functionality, you should also be overriding Equals and GetHashCode so that they return a consistent set of responses to callers.
Try a.ReferenceEquals(b);
To check whether both points to same object. You should use Object.ReferenceEquals method. It will return true if both are same or if both are null. Else it will return false
I know its an old question, but if you're going to overload the == or Object.Equals method, you should also overload the reverse operator !=.
And in this case, since you're comparing internal numbers, you should overload the other comparison operators <, >, <=, >=.
People who consume your class in the future, whether it be third-party consumers, or developers who take over your code, might use something like CodeRush or Refactor, that'll automatically "flip" the logic (also called reversing the conditional) and then flatten it, to break out of the 25 nested if's syndrome. If their code does that, and you've overloaded the == operator without overloading the != operator, it could change the intended meaning of your code.