Is there a difference between x is null and ReferenceEquals(x, null)? - c#

When I write this:
ReferenceEquals(x, null)
Visual studio suggests that the
null check can be simplified.
and simplifies it to
x is null
Are those really the same?

I noticed a lot of answers specifying that x == null, x is null, and ReferenceEquals(x, null) are all equivalent - and for most cases this is true. However, there is a case where you CANNOT use x == null as I have documented below:
Note that the code below assumes you have implemented the Equals method for your class:
Do NOT do this - the operator == method will be called recursively until a stack overflow occurs:
public static bool operator ==(MyClass x1, MyClass x2)
{
if (x1 == null)
return x2 == null;
return x1.Equals(x2)
}
Do this instead:
public static bool operator ==(MyClass x1, MyClass x2)
{
if (x1 is null)
return x2 is null;
return x1.Equals(x2)
}
Or
public static bool operator ==(MyClass x1, MyClass x2)
{
if (ReferenceEquals(x1, null))
return ReferenceEquals(x2, null);
return x1.Equals(x2)
}

Are those really the same?
Semantically yes (assuming x is not a value type). You're doing a null check which is the same for all reference types.
Implementation: no. x == null or x is null will be directly implemented as IL instructions but Object.ReferenceEquals(x, null) will be a method call.1
Also note if the type of x has overridden operator == then x == null may not be equivalent (changing the semantics of null checks in an operator overload is, at best, poor code because no one expects such a semantic change).
1 Of course the optimiser could recognise this and just output the IL, you'll need to look at the IL to confirm this.

I realize that I'm supre-late to the party and that answers have been given, but I feel the need to summarize a bit since this is a thing I search for every 8-12 months or so and I'd like to have an explanation I can understand (hopefully, if it gets posted)..
1. ReferenceEquals(a,b)
This is the tried and tested method to perform a safe reference equality comparison. It basically performs (object)a == (object)b (or something to that effect) and has the advantages that its use is instantly recognizable and it can't be overridden.
2. a == b
This method is the one that feels "natural" to most people (since most comparison done throughout C# will be done with this operator).
Default behaviour on reference types should be correct. However, this can be overloaded, which can lead to unexpected results (imagining a failed implementation of the operator overload).
Like #mdebeus said, an additional risk (however marginal even for a competent monkey that read a primer on C#) is causing a StackOverflowException. This can appear when overloading == and != and using the operators inside the method itself.
3. a is b
OK so this is shiny new sort of sugary thing that we get. Microsoft describes is in this case with:
The is operator checks if the runtime type of an expression result is compatible with a given type.
[...]
The E is T expression returns true if the result of E is non-null and
can be converted to type T by a reference conversion, a boxing
conversion, or an unboxing conversion; otherwise, it returns false.
The is operator doesn't consider user-defined conversions.
(read a complete description here)
The short of it is that this will return true if a can be converted through b via boxing, unboxing or covariance.
As you would expect, this works very well against null.
All in all, as a personal note, although is makes things shorter and prettier for null check in equality overloading, I think I'll would still use ReferenceEquals, simply because I'm a control-freak and there is at least a part of how is works that worries me when it comes to cases of covariance.

They mean the same in this case, yes. Most would use x == null though.
I guess ReferenceEquals could be little bit confusing because actually null is a literal that means no reference at all. How can any reference be equal to no reference?
Note that x is null is only allowed with C#7 and it's pattern matching feature. Normally you use is to check if x is a compatible type but null is not a type. So this is a bit confusing as well.
That's why i prefer x == null

Related

Does the ?? operator guarantee only to run the left-hand argument once?

For example, given this code:
int? ReallyComplexFunction()
{
return 2; // Imagine this did something that took a while
}
void Something()
{
int i = ReallyCleverFunction() ?? 42;
}
... is it guaranteed that the function will only be called once? In my test it's only called once, but I can't see any documentation stating I can rely on that always being the case.
Edit
I can guess how it is implemented, but c'mon: we're developers. We shouldn't be muddling through on guesses and assumptions. For example, will all future implementations be the same? Will another platform's implementation of the language be the same? That depends on the specifications of the language and what guarantees it offers. For example, a future or different platform implementation (not a good one, but it's possible) may do this in the ?? implementation:
return ReallyComplexFunction() == null ? 42 : ReallyComplexFunction();
That, would call the ReallyComplexFunction twice if it didn't return null. (although this looks a ridiculous implementation, if you replace the function with a nullable variable it looks quite reasonable: return a == null ? 42 : a)
As stated above, I know in my test it's only called once, but my question is does the C# Specification guarantee/specify that the left-hand side will only be called once? If so, where? I can't see any such mention in the C# Language Specification for ?? operator (where I originally looked for the answer to my query).
The ?? operator will evaluate the left side once, and the right side zero or once, depending on the result of the left side.
Your code
int i = ReallyCleverFunction() ?? 42;
Is equivalent to (and this is actually very close to what the compiler actually generates):
int? temp = ReallyCleverFunction();
int i = temp.HasValue ? temp.Value : 42;
Or more simply:
int i = ReallyCleverFunction().GetValueOrDefault(42);
Either way you look at it, ReallyCleverFunction is only called once.
The ?? operator has nothing to do with the left hand. The left hand is run first and then the ?? operator evaluates its response.
In your code, ReallyCleverFunction will only run once.
It will be only called once. If the value of ReallyCleverFunction is null, the value 42 is used, otherwise the returned value of ReallyCleverFunction is used.
It will evaluate the function, then evaluate the left value (which is the result of the function) of the ?? operator. There is no reason it would call the function twice.
It is called once and following the documentation I believe this should be sufficient to assume it is only called once:
It returns the left-hand operand if the operand is not null; otherwise
it returns the right operand.
?? operator
It will only be run once because the ?? operator is just a shortcut.
Your line
int i = ReallyCleverFunction() ?? 42;
is the same as
int? temp = ReallyCleverFunction();
int i;
if (temp != null)
{
i = temp.Value;
} else {
i = 42;
}
The compiler does the hard work.
Firstly, the answer is yes it does guarantee it will only evaluate it once, by inference in section 7.13 of the official C# language specification.
Section 7.13 always treats a as an object, therefore it must only take the return of a function and use that in the processing. It says the following about the ?? operator (emphasis added):
• If b is a dynamic expression, the result type is dynamic. At run-time, a is first evaluated. If a is not null, a is converted to dynamic, and this becomes the result. Otherwise, b is evaluated, and this becomes the result.
• Otherwise, if A exists and is a nullable type and an implicit conversion exists from b to A0, the result type is A0. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0, and this becomes the result. Otherwise, b is evaluated and converted to type A0, and this becomes the result.
• Otherwise, if A exists and an implicit conversion exists from b to A, the result type is A. At run-time, a is first evaluated. If a is not null, a becomes the result. Otherwise, b is evaluated and converted to type A, and this becomes the result.
• Otherwise, if b has a type B and an implicit conversion exists from a to B, the result type is B. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0 (if A exists and is nullable) and converted to type B, and this becomes the result. Otherwise, b is evaluated and becomes the result.
As a side-note the link given at the end of the question is not the C# language specification despite it's first ranking in a Google Search for the "C# language specification".

Using an "is" check when with an explicit cast [duplicate]

This question already has answers here:
Casting vs using the 'as' keyword in the CLR
(18 answers)
Closed 9 years ago.
How does the "is" operator work in C#?
I have been told that this :
if (x is string)
{
string y = x as string;
//Do something
}
is not as good as this:
string y = x as string;
if (y != null)
{
//Do something
}
Which is better and why?
FxCop issues Warning CA1800 in the first scenario (and not only when using as, but also when using an unchecked cast) as both is and the actual casts require certain type checking operations to determine whether the cast is successful or whether to throw an InvalidCastException.
You might save a few operations by just using as once and then checking the result for null if you are going to use the cast value anyway, rather than checking explicitly with is and then casting anew.
I think second is better cause in first case it will cast object 2 times, first time with is operator and second time in as operator.
while in second case it cast only one time.
The is operator checks if an object can be cast to a specific type or not
like
if (someObj is StringBuilder)
{
StringBuilder ss = someObj as StringBuilder
....
}
The as operator cast an object to a specific type, and returns null if it fails.
like
StringBuilder b = someObj as StringBuilder;
if (b != null) ...
I would use the first approach when more than one type is expected to be stored in x. (You might be passed a string, or a StringBuilder etc). This would allow for non-exception based handling.
If you are always expecting x to hold a certain type of value, then I would use the second option. The check for null is inexpensive and provides a level of validation.
-- Edit --
Wow. After reading some of the comments below, I started looking for more updated information. There is a LOT more to consider, when using as vs is vs (casting). Here are two interesting reads I found.
Does it make sense to use "as" instead of a cast even if there is no null check? and http://blogs.msdn.com/b/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx?PageIndex=1#comments
Both of which seem to be well summarized by Jon Skeet's blog. http://www.yoda.arachsys.com/csharp/faq/#cast.as

Avoid == and != operators on generic type parameters, but can it compare with null?

According to the Constraints on Type Parameters (C# Programming Guide) documentation it says, and I quote:
When applying the where T : class constraint, avoid the == and !=
operators on the type parameter because these operators will test for
reference identity only, not for value equality. This is the case even
if these operators are overloaded in a type that is used as an
argument. The following code illustrates this point; the output is
false even though the String class overloads the == operator.
With the following example:
public static void OpTest<T>(T s, T t) where T : class
{
System.Console.WriteLine(s == t);
}
static void Main()
{
string s1 = "target";
System.Text.StringBuilder sb = new System.Text.StringBuilder("target");
string s2 = sb.ToString();
OpTest<string>(s1, s2);
}
However, ReSharper (I've just started using the demo/trial version to see if it is any worth to me) gives a hint/tip to do null-checking of parameters like so:
public Node(T type, Index2D index2D, int f, Node<T> parent)
{
if (type == null) throw new ArgumentNullException("type");
if (index2D == null) throw new ArgumentNullException("index2D");
if (parent == null) throw new ArgumentNullException("parent");
}
(T is constrained with where T : class, new())
Can I safely follow ReSharper without running into problems that the C# documentation is trying to tell me to avoid?
Yes, that is fine. The documentation says not to compare two parameters because you're doing a reference comparison. The code ReSharper suggests is just ensuring the reference you've been passed is not null so that is safe to do.
In my opinion the main reason the C# docs recommend you don't do that is because if for example you do == with two strings that were passed as T1 and T2 it will do a reference comparison. Any other time you do stringA == stringB it will do a value comparison with the overload in the string class. It's really just warning against doing these types of comparisons because the operator overload that would normally be used (if you used that operator on two types declared in local scope) is not.
Yes.
Only a very strange implementation of the == operator would make x == null mean something other than ReferenceEquals(x, null). If you are using classes that have such a strange implementation of equality, you have bigger problems than it being inconsistent when checking for null using a generic type argument.
The documentation is telling you that == will use a reference comparison regardless of what the actual type of T is, even if it has overloaded the == operator. In many cases this isn't what users would expect.
In the case of the resharper code it's comparing the variable to null, which you want to be a reference comparison, not a value comparison, so what the documentation is warning you of is the correct behavior here.
You could however make it a bit more explicit by writing something like this, just to be clearer:
if(object.ReferenceEquals(type, null))//...
Yes, it's generally ok to assume that null is a special case, and that it's okay to do == or != on it. This is due, in part at least, to the fact that the recommendation for overriding Equals says that x.Equals(null) should be false.
If you didn't have the T : class constraint, it'd be a different story, since you'd see some possibly-unexpected behavior for structs and nullable structs (you might want to do default(T) instead of null there).
And if you want to be explicit that yes, you know you're comparing the reference to null, you can always use object.ReferenceEquals(x, null) (I'd just go with ==/!=, though).
I would say that this is OK.
null is kinda special, so you are not doing an actual comparison between two reference variables, you are just assuring that the reference variable is not a null reference.
Compare this with, for example, SQL. There you have a completely different syntax for comparing ( a = b) and for the null check (a is null). The guideline is that you should avoid the first, but the second is ok.

ReferenceEquals(variable, null) is the same as variable == null?

Basically the title. I see a lot of the former in the code I'm working on and I was wondering why they didn't use the latter. Are there any differences between the two?
Thanks.
Straight from the documentation
Unlike the Equals method and the equality operator, the ReferenceEquals method cannot be overridden. Because of this, if you want to test two object references for equality and are unsure about the implementation of the Equals method, you can call the ReferenceEquals method. However, note that if objA and objB are value types, they are boxed before they are passed to the ReferenceEquals method.
Not really. One can overload operator ==, so you basically can get it return e.g. false always. The recommended usage for this operator is to signify value equality, so (for correcftly implemented operator) basically check against null may return true if the object is semantically null.
See this article for more details and some historical overview.
Another difference is that for value types ReferenceEquals doesn't make much sense: for example, any two "instances" of int 0 have to be considered the same in any sane circumstances. (For purists: I put quotes because, strictly speaking, we cannot talk about instances of a value type.)
The main benefit of ReferenceEquals() is that the intention is much clearer, you are trying to determine if two references are equal, not if the contents of the objects referred to are equal.
It does this by checking for operator == equality between the two references cast to object (since the params are both object), which eliminates any subclass operator == overloads that might confuse the issue (like string's).
So essentially, this:
if (ReferenceEquals(x, y))
Is the same as this:
if (((object)x) == ((object)y))
Though the former is easier to read.
There are definitely times where it comes in handy, especially avoiding infinite recursion when you are overloading operator == yourself:
public class Foo
{
public static bool operator ==(Foo first, Foo second)
{
// can't say if (first == second) here or infinite recursion...
if (ReferenceEquals(first, second))
{
// if same object, obviously same...
return true;
}
// etc.
}
}

Why nullable types will not be equal in this case?

Surprisingly the code bellow will not succeed.
int? n1 = null;
int? n2 = null;
Assert.IsTrue(n1 <= n2); // Fails here
Do you know why?
Using boolean logic with null nullable values in C# (and VB.Net) often times defies logic. I find the best way to make sense of it is to remember that "null is not a value". Because null is not a value you cannot do any operations on it. Hence things like "1 > null" and "1 < null" are both true.
Here is a detailed guide: http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx
If you do want to treat null as a value then you could use the GetValueOrDefaultMethod() to equate null with the default value. For example
Assert.IsTrue(n1.GetValueOrDefault() <= n2.GetValueOrDefault()); // True
This is a bit verbose but it will get the job done.
Either this is a typo and you meant "==" not "<=" or you misunderstand how nulls work.
In almost all languages (including c#) the only default legal operation on null is to check if something else is equal to it (in .Net == is by default reference equality).
<= and >= are not meaningful (as they would have very strange behaviour if they did)
Some languages (SQL being possibly the most well known) disallow the use of 'standard' equality operators to make this even more clear. in SQL null == null is NOT true, and a compliant server will refuse queries where you attempt to do this via a literal.
C# takes the same route as it's heritage (C style imperative languages) where the test for a null value is based on testing that the bits in it are zero (things get somewhat more complex but fundamentally that's what is happening). As such only reference types can truly be null (Nullable<T> has a lot of magic behind the scenes to make it look like it is but actually under the hood it isn't null). This means that the reference equality semantics follow nicely into null semantics, thus the == null is allowed.
Other languages implement null in a different fashion (for example SQL where anything can be made null thus the 'nullness' of something must be stored outside of it (much like Nullable). This means that the conventional use of equality need not be the primary concern and null can be truly special rather than a special case of certain types.
For further information on the specialness of null take a look at This question has a list of such languages
Most reference types do not define a >= or <= operator so there is little problem in practice with the disconnect between == and <= (where normally if something is true for == it would be true for <= and >= as well).
You can try this:
int? n1 = null;
int? n2 = null;
// Test for equality
Assert.IsTrue((n1.HasValue && n2.HasValue && n1.Value == n2.Value) || (!n1.HasValue && !n2.HasValue));
// Test for less than or equal to
Assert.IsTrue(n1.HasValue && n2.HasValue && n1.Value <= n2.Value);
Nullable types are wrapped into a System.Nullable object, so you don't compare the int value, you compare the reference. To compare the values, you need to make it like that:
Assert.IsTrue(n1.Value <= n2.Value);
I wrote a bit about nullable on my blog.
Edit:
But in your case n1 and n2 is null, so you can't even compare the values.

Categories

Resources