See below code first please.
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
public struct MyStruct
{
public List<MyStructItem> Items;
}
public struct MyStructItem
{
public string Value;
}
static void Main(string[] args)
{
List<MyStruct> myList = new List<MyStruct>();
myList.Add(new MyStruct());
//(!) it haven't comipled.
if (myList[0].Items = null){Console.WriteLine("null!");}
//(!) but it have compiled.
if (myList[0].Items != null) { Console.WriteLine("not null!"); }
}
}
}
What is difference between !=null and =null in that case?
thanks.
You are using the assignment operator = instead of the equality operator ==.
Try:
//(!) it haven't comipled.
if (myList[0].Items == null){Console.WriteLine("null!");}
//(!) but it have compiled.
if (myList[0].Items != null) { Console.WriteLine("not null!"); }
The difference is one compiles and one doesn't :-)
C# Operators:
http://msdn.microsoft.com/en-us/library/6a71f45d(v=vs.80).aspx
= null is assignment. You should use == null
You assign the null value to myList[0].Items and tries to use it as bool in if statement. That is why code can not be compiled.
For example, this code compiles successfully:
bool b;
if (b = true)
{
...
}
Because you set true value to b and then check it in if statement.
=null you set the value to null
!= null you check if it is different from null
If you want to compare if it is equal to null, use == null instead of = null.
'=' is for assignment, not for comparing. Use '=='
if (myList[0].Items == null){Console.WriteLine("null!");}
First off, myList[0].Items = null will set the object to null. You probably mean myList[0].Items == null
And regarding the difference, == checked if something is equal. != checks if something is not equal.
For predefined value types, the equality operator (==) returns true if
the values of its operands are equal, false otherwise. For reference
types other than string, == returns true if its two operands refer to
the same object. For the string type, == compares the values of the
strings.
And
The assignment operator (=) stores the value of its right-hand operand
in the storage location, property, or indexer denoted by its left-hand
operand and returns the value as its result. The operands must be of
the same type (or the right-hand operand must be implicitly
convertible to the type of the left-hand operand).
Reference: http://msdn.microsoft.com/en-us/library/6a71f45d(v=vs.71).aspx
= is the assignment operator, you should use the equality operator ==
= null is an assignment. == null is a condition.
if (myList[0].Items != null)
is a negative comparison. It checks if myList[0].Items is not equal to null.
if (myList[0].Items = null)
is an assignment. It would normally assign null to myList[0].Items and return true (in languages like C++), however, in C#, this won't compile (because of this common error).
Related
How does it work?
public class Node
{
Node Left ;
Node Right ;
}
...
var a = new Node();
var b = new Node();
if (a.Right == b.Right == null) // <- compiles and resharper says it's always false
{
}
var aa = 1;
var bb = 2;
if (aa == bb == 0) // doesn't compile Cannot apply operator '==' to operands of type 'bool' and 'int'
{
}
Why do multiple comparands work with 'Node' and doesn't work with 'Int'?
An expression like
a == b == c
is interpreted as
(a == b) == c
so first a == b is evaluated and returns either true or false, a boolean.
Then someBool == c is evaluated. If c is 0, then you are comparing a bool against an int, which leads to your compile error.
However if c is null, then both that null and that "someBool" are promoted lifted to a Nullable<bool> (or bool?), so they can be compared. But of course a true or false is never equal to (bool?)null, which is what Resharper says.
So you cannot take this shortcut and will have to write it as
(a == c) && (b == c)
Or in your case:
if (a.Right == null && b.Right == null) ...
if (aa == 0 && bb == 0) ...
In short, you can't compare like this, ever...
In regards to if (a.Right == b.Right == null)
It compiles because you can compare a non-nullable value types with null and it's always false.
a.Right == b.Right // bool
bool == null //will be lifted and always equal false (see below)
To know the reason why you'll have to visit the specs and understand lifted operators
12.4.8 Lifted operators
Lifted operators permit predefined and user-defined operators that
operate on non-nullable value types to also be used with nullable
forms of those types
For the equality operators == !=
a lifted form of an operator exists if the operand types are both
non-nullable value types and if the result type is bool. The lifted
form is constructed by adding a single ? modifier to each operand
type. The lifted operator considers two null values equal, and a null
value unequal to any non-null value. If both operands are non-null,
the lifted operator unwraps the operands and applies the underlying
operator to produce the bool result.
In regards to if(aa == bb == 0) you can't compare bool with an int, there is no implicit conversion to bool
aa == bb // bool
bool == 0 // there is no implicit conversion to bool
Why do multiple comparands work with 'Node' and doesn't work with
'Int'?
A) I guess you should be asking why it works with Null and not Int values. In your example above Node is a reference type and integer 0 is a value type. Read details below
All Value Types can be compared to null because they are convertible to nullable and null is the default value assigned to a Reference Types
Value types include : Bool, Integers, Floating points, char
Reference types include : Class, string, objects, interface
Valid Cases:
bool a =true;
if(a == null) //a is converted to a Nullable Boolean and then compared with null`
if(a.Right==b.Right==null) //First 2 statements are evaluated to boolean, which is converted to a Nullable Boolean and then compared with null`
int i=5;
if(i==null) // i is converted to a Nullable int and then compared with null, which always ends up false as the value of i is 5
Nullable<int> ii = 5;
if(ii==null) // ii being a nullable int is compared with null, there will not be any warnings indicated by the compiler as it know before hand that ii has a chance of being null
int a =5; int b=4;
if(a==b) // Valid, because your comparing 2 Integers are equal
Invalid Cases:
int a =5; int b=4;
if(a==b==0) // First 2 statements evaulate to a boolean and a boolean is evaluated to a Integer, the compiler fails to understand how to convert a Boolean to Int and hence the error
if(a==true) // same as above, compiler fails to compare an integer to a boolean and results in an error
I have this very simple example:
class Program
{
class A
{
public bool B;
}
static void Main()
{
System.Collections.ArrayList list = null;
if (list?.Count > 0)
{
System.Console.WriteLine("Contains elements");
}
A a = null;
if (a?.B)
{
System.Console.WriteLine("Is initialized");
}
}
}
The line if (list?.Count > 0) compiles perfectly which means that if list is null, the expression Count > 0 becomes false by default.
However, the line if (a?.B) throws a compiler error saying I can't implicitly convert bool? to bool.
Why is one different from the other?
list?.Count > 0: Here you compare an int? to an int, yielding a bool, since lifted comparison operators return a bool, not a bool?.
a?.B: Here, you have a bool?. if, however, requires a bool.
In your first case (list?.Count) the operator returns an int? - a nullable int.
The > operator is defined for nullable integers so that if the int? has no value (is null), the comparison will return false.
In your second example (a?.B) a bool? is returned (because if a is null, neither true nor false but null is returned). And bool? cannot be used in an if statement as the if statement requires a (non-nullable) bool.
You can change that statement to:
if (a?.B ?? false)
to make it work again. So the null-coalescing operator (??) returns false when the null-conditional operator (?.) returned null.
Or (as TheLethalCoder suggested):
if (a?.B == true)
Observation: If text is null, this method returns True. I expected False.
return text?.IndexOf('A') != -1;
When I reflect the above line using ILSpy (or inspect the IL), this is the generated code:
return text == null || text.IndexOf('A') != -1;
Here is what I really need to meet my expectation:
return text != null && text.IndexOf('A') != -1;
Question: Does someone have a good explanation about why the Null Conditional code generated the OR expression?
Full Sample at: https://dotnetfiddle.net/T1iI1c
The line above really involves two operations: a null-conditional operator method call, and a comparison. What happens if you store the result of the first operator as an intermediate variable?
int? intermediate = text?.IndexOf('A');
return intermediate != -1;
Clearly if text is null then intermediate will also be null. Comparing this with any integer value using != will return true.
From MSDN (emphasis mine):
When you perform comparisons with nullable types, if the value of one of the nullable types is null and the other is not, all comparisons evaluate to false except for != (not equal).
This code can be written using the null-conditional operator as long as you can use a different operator to ensure a comparison with null evaluates to false. In this case,
return text?.IndexOf('A') > -1;
will return the output you expected.
Something like the ternary operator (?:) or the null coalescing operator (??). It seems silly to me to take up two lines and be so wordy when the other operators exist.
EDIT:
Since it's requested, here's two possible examples of what I hope that I can find
var variable ?= mightBeNull;
or
var variable = mightBeNull != null ? mightBeNull
Really, it's either something that can be used to assign a value, if it's not null, to a variable or an If without an Else packaged nicely in an operator.
The ??= operator is coming to C# 8.
int? i = null; // i = null
i ??= 0; // i = 0
i ??= 1; // i = 0
// different ways of writing 'i ??= 0;':
i = i ?? 0;
if (i == null) i = 0;
So you want this?
if (other != null)
someVariable = other;
You could do the following, but I'd argue that the above is better due to clarity and possible side effects:
someVariable = other ?? someVariable;
The above might cause side effects if someVariable is a property and either the get or set can cause side effects; this shouldn't be important if your property follows the ordinary guidelines. Or, as Servy points out, even if it's a field, it could created different semantics in a multithreaded app. I should note that in the first example, you read other twice, which also has the potential for complexity to enter (though a smaller potential than the latter example).
I bet this is what you are looking for.
Let's say we have a function, myFunction that says whether the argument passed input is null or not. If input is null, it will return "Input is null!", else it will return "Input is not null".
This is the normal approach:
public String myFunction(string input) {
if (input == null)
return "Input is null!";
else
return "Input is not null";
}
And this is the other approach (What you are looking for):
public String myFunction(string input) {
return (input == null) ? "Input is null!" : "Input is not null";
}
It is called (?: conditional operator).
To assign a value to a variable only if it is not null, you would need to use an if. Neither the conditinal nor the null coalesce operators would do that.
if(somethingElse != null) something = somethingElse;
There is no specific operator in C# that does exactly this.
In Visual Studio 2015 C# there is a new operator called the Null-Conditional that does what you are asking. It is the ?. or ? operator.
int? length = customers?.Length; // null if customers is null
Customer first = customers?[0]; // null if customers is null
int? count = customers?[0]?.Orders?.Count(); // null if customers, the first customer, or Orders is null
Currently useable in previous versions of C# but not an operator but rather a one liner would be to use the ? : statement
?: operator
condition ? first_expression : second_expression;
AssingningTO = (someVar == null) ? null: someVar; // if null assign null ELSE assign someVar
AssingningTO = (someVar == null) ? String.Empth(): someVar; // if null assign empty string else someVar
Nullable types can represent all the values of an underlying type, and an additional null value.
http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx
I have a simple line of code: lead.InternalCompany = nvCollection["ic"];
I want to set lead.InternalCompany to the value retrieved, but if nothing is there to a blank string ""
I've tried to use nvCollection["ic"].HasValue();
I know I could do something simple like this
string value = nvCollection["ic"];
if (value == null) // key doesn't exist
{
lead.InternalCompany = "";
}
I'd ideally like a ternary if statement to accomplish this
Use the null-coalescing operator
The ?? operator is called the null-coalescing operator and is used to
define a default value for nullable value types or reference types. It
returns the left-hand operand if the operand is not null; otherwise it
returns the right operand.
lead.InternalCompany = nvCollection["ic"] ?? string.Empty;