Could you please explain, why does Console.WriteLine write empty line (Console.WriteLine(null) give me compilation error) and why there isn't NullReferenceException (even a+=1 shouldn't raise it)?
int? a = null;
a++; // Why there is not NullReferenceException?
Console.WriteLine(a); // Empty line
You're observing the effects of a lifted operator.
From section 7.3.7 of the C# 5 specification:
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. Lifted operators are constructed from predefined and user-defined operators that meet certain requirements, as described in the following:
For the unary operators + ++ - -- ! ~
a lifted form of an operator exists if the operand and result types are both non-nullable value types. The lifted form is constructed by adding a single ? modifier to the operand and result types. The lifted operator produces a null value if the operand is null. Otherwise, the lifted operator unwraps the operand, applies the underlying operator, and wraps the result.
So basically, a++ in this case is an expression with a result of null (as an int?) and the variable is left untouched.
When you call
Console.WriteLine(a);
that's being boxed into object, which converts it to a null reference, which is printed as an empty line.
Jon's answer is correct but I would add some additional notes.
Why does Console.WriteLine(null) give a compilation error?
There are 19 overloads of Console.WriteLine and three of them are applicable to a null: the one that takes a string, the one that takes a char[] and the one that takes an object. C# cannot determine which of these three you mean, so it gives an error. Console.WriteLine((object)null) would be legal because now it is clear.
why does Console.WriteLine(a) write an empty line?
a is a null int?. Overload resolution chooses the object version of the method, so the int? is boxed to a null reference. So this is basically the same as Console.WriteLine((object)null), which writes an empty line.
Why there is not NullReferenceException on the increment?
Where's the null reference that you are worried about? a is a null int? which is not a reference type to begin with! Remember, nullable value types are value types, not reference types, so don't expect them to have reference semantics unless they are boxed to a reference type. There is no boxing in the addition.
Are You incrementing null???
int? a = null;
a++;
This statement simply means null++ i.e. null+1.
As per this document, A nullable type can represent the correct range of values for its underlying value type, plus an additional null value.A Nullable, pronounced "Nullable of Int32," can be assigned any value from -2147483648 to 2147483647, or it can be assigned the null value
Here you are incrementing null, then also it will become null value not 0 or any other integer.
Why it prints blank instead of error??
when you print a nullable type with null value it prints blank instead of error because you are printing a variable i.e. value of a memory location. which maybe null or any integer.
But when you try to print null using Console.WriteLine(null), as null is not a variable, so it doesn't refer to any memory location. And hence it gives error "NullReferenceException".
Then how can you print any integer using Console.WriteLine(2); ??
In this case, 2 will gets in memory at temporary location, and the pointer points to that memory location to print.
Related
This question already has an answer here:
Casting an object using the "as" keyword returns null
(1 answer)
Closed 3 years ago.
long? i = 10000;
int? s = i as int?;
Why is it giving me a null in s variable? I know that casting it using int? s = (int?)i; will work fine but why can't I use an as operator?
From MSDN:
The code is equivalent to the following expression except that the expression variable is evaluated only one time.
expression is type ? (type)expression : (type)null
Since i is int? is false the as keyword will return (int?)null.
The types aren't equivalent and you get null, that is just how as works
However, you could just direct Cast
long? i = 10000;
var s = (int?)i;
// or even better make sure its *checked*
var s = checked((int?)i);
Why does this work?
C# Language Specification 11.6.1 Nullable Conversions
...
Evaluation of a nullable conversion based on an underlying conversion
from S to T proceeds as follows:
If the nullable conversion is from S? to T?:
If the source value is null (HasValue property is false), the result is the null value of type T?.
Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a
wrapping from T to T?.
...
as does not do this, it checks the run-time types, if they are not equal returns null T?
Additional Resources
checked (C# Reference)
The checked keyword is used to explicitly enable overflow checking for
integral-type arithmetic operations and conversions.
#Update from comments
I got that we can't convert and why we can't do I but why they are
suggesting it is there any scenario where it will be useful i'e some
random image link of Compiler Error CS0077 "The as operator must be used with a reference type or nullable type ('int' is a non-nullable value type)."
The reason is (in your image example) a value type can't be null it could never work with it. The thing you are missing is there are more complex examples of what could happen, you can define implicit operators on custom types, etc.
The compiler cannot implicitly convert 'long' to 'int'
And as per MSDN
The as operator is like a cast operation. However, if the conversion
isn't possible, as returns null instead of raising an exception.
ref: as (C# Reference)
So with your code, conversion is not possible, as is returning Null.
The Nullable<T> type is defined as a struct. In .Net, you can't assign null to a struct because structs are value types that cannot be represented with null (with the exception of Nullable<T>).
int i = null; // won't compile - we all know this
int? i = null; // will compile, and I'm glad it does, and it should compile, but why?
How did Nullable<T> become an exception to the rule "You can't assign null to a value type?" The decompiled code for Nullable<T> offers no insights as of to how this happens.
How did Nullable<T> become an exception to the rule "You can't assign null to a value type?"
By changing the language, basically. The null literal went from being "a null reference" to "the null value of the relevant type".
At execution time, "the null value" for a nullable value type is a value where the HasValue property returns false. So this:
int? x = null;
is equivalent to:
int? x = new int?();
It's worth separating the framework parts of Nullable<T> from the language and CLR aspects. In fact, the CLR itself doesn't need to know much about nullable value types - as far as I'm aware, the only important aspect is that the null value of a nullable value type is boxed to a null reference, and you can unbox a null reference to the null value of any nullable value type. Even that was only introduced just before .NET 2.0's final release.
The language support mostly consists of:
Syntactic sugar in the form of ? so int? is equivalent to Nullable<int>
Lifted operators
The changed meaning of null
The null-coalescing operator (??) - which isn't restricted to nullable value types
The Nullable<T> type is defined as a struct. In .Net, you can't assign null to a struct because structs are value types that cannot be represented with null (with the exception of Nullable<T>).
int i = null; // won't compile - we all know this
int? i = null; // will compile, and I'm glad it does, and it should compile, but why?
How did Nullable<T> become an exception to the rule "You can't assign null to a value type?" The decompiled code for Nullable<T> offers no insights as of to how this happens.
How did Nullable<T> become an exception to the rule "You can't assign null to a value type?"
By changing the language, basically. The null literal went from being "a null reference" to "the null value of the relevant type".
At execution time, "the null value" for a nullable value type is a value where the HasValue property returns false. So this:
int? x = null;
is equivalent to:
int? x = new int?();
It's worth separating the framework parts of Nullable<T> from the language and CLR aspects. In fact, the CLR itself doesn't need to know much about nullable value types - as far as I'm aware, the only important aspect is that the null value of a nullable value type is boxed to a null reference, and you can unbox a null reference to the null value of any nullable value type. Even that was only introduced just before .NET 2.0's final release.
The language support mostly consists of:
Syntactic sugar in the form of ? so int? is equivalent to Nullable<int>
Lifted operators
The changed meaning of null
The null-coalescing operator (??) - which isn't restricted to nullable value types
Originally I had this impression that NULL is reference type because it is assigned to references, then encountered this concept called nullable value types, this makes my theory in an awkward situation, so is NULL value type of reference type on earth ?
The C# specification is clear on this point: the null keyword represent an expression that has no type. It is neither reference type nor value type nor pointer type. However that expression is convertible to all of those types. There is no requirement that the compiler classify all expressions as having a type, and in fact it does not.
Now you might then ask at runtime what is the type of a null reference, what is the type of a null value of nullable value type, and what is the type of a null pointer. The answers are:
a null reference does not have a type. If you have a box that can hold chocolates it is pointless to ask "what brand of chocolates are in this empty box?" A missing chocolate does not have a brand; a null reference does not have a type.
similarly, the type of a null pointer is, again, not anything; null pointer values don't point to anything. If you have a piece of paper that has the address 1600 Pennsylvania Avenue on it, you can ask "what is the colour of the house at this address", and get the answer: white. If you have a blank piece of paper, asking what the colour of the house at that address is doesn't get you any useful answer.
a null value of a nullable value type is a value of the nullable value type.
null isn't a type.
From msdn:
The null keyword is a literal that represents a null reference, one that does not refer to any object.
Nullable types are instances of the Nullable<T> struct which "Represents a value type that can be assigned null."
Neither. null is the default value for reference types, but it does not have a type itself.
Nullable value types are actually implemented as value types themselves - there are just compiler and library tricks to make them behave as expected when compared to null.
null doesn't have a type by itself in C#, as it was already said here. I think some precise examples showing the implications of this definition are missing from the other answers.
var something = null;
is invalid
string a = null; // valid. Null is implicitely casted to string.
int? b = null; // valid. Null is implicitely casted to Nullable<int>.
var c = "hello" // valid, type of c is infered by the compiler by looking at the right side of the expression.
var d = null; // not valid, compiler can't infer any type from null !
The invalid line in the above example will cause the following compilation error :
Error - CS0815 - Cannot assign to an implicitly-typed variable
and also :
Passing null to overloaded methods might require an explicit cast
void myMethod(int? myParam) { }
void myMethod(string myParam) { }
void test
{
string a = null;
myMethod(a); // no problem here, a is of type string so 2nd overload will be used.
myMethod(null); // not valid ! Compiler can't guess which one you want.
myMethod((string) null); // valid, null is casted to string so 2nd overload is to be used.
}
The invalid line in the above example will cause the following compilation error :
Error - CS0121 - The call is ambiguous between the following methods
or properties: 'myMethod(string)' and 'myMethod(int?)'
null does not reference to anything. It is just a type points to nothing. You people usually use it to de-reference an object.
The null keyword in C# does represent a null reference, so you can consider it a reference type (although technically it indicates not type).
The C# compiler and extra handling of null for use with nullable types. Nullable value types and value types and can never actually be null. When you assign or compare a Nullable value type to null the compiler will replace the code.
For example:
int? i;
if (i == null)
i = 1;
Is replaced by the compiler with:
int? i;
if (!i.HasVaue)
i = 1;
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What's the difference between 'int?' and 'int' in C#?
I've come across some code in C# that declares a variable as: int? number
What does the ? mean and how does this differ from just: int
int cannot be null.
int? is an alias for the Nullable<int> struct, which you can set to null.
int? is a shorthand for creating an instance of the generic System.Nullable<T> structure type. It allows you to make your variable nullable. Remember, given that the <ValueType>? syntax is a shorthand, you could declare your variables thus:
Nullable<int> i = 10;
int? is shorthand for Nullable<int> which allows you to pretend that an integer can handle nulls.
int? foo = null;
It is useful for indicating a lack of value where you would previously have used a magic value (-1) in the past, and also useful when dealing with database columns that allow null entries.
For a quasi-in-depth look, a Nullable<T> (introduced in .NET 2.0) is simply a wrapper over a value type T that exposes two properties, HasValue and Value, where HasValue is a boolean that indicates if the value has been set and Value (obviously enough) returns the value. It is an error to access Value if HasValue is false. Therefore, to access Value, it is good form to check HasValue first. Additionally, if you simply want to normalize any non-values to default values (0 for numeric types), you can use the method GetValueOrDefault() without needing to check HasValue.
Note that although you appear to set foo to null, it's not actually null under normal usage scenarios. null is simply additional syntactic sugar for this type. The above line of code translates to
Nullable<int> foo = new Nullable<int>();
Initializing the variable in this fashion simply sets the HasValue property to false.
However, in situations involving boxing, the value will actually box to null if HasValue is false (it will otherwise box to T). Be aware of the consequences! For example, in:
int? foo = null;
string bar = foo.ToString(); // this is fine, returns string.Empty
Type type = foo.GetType(); // blows up! GetType causes the value to box
// resulting in a NullReferenceException
That's a quick crash course. For more, visit the documentation.
It's syntactic compiler sugar for Nullable<int>
Basically your number (or any other value type) can be null as well as it's value. You check for a value using the HasValue property. They can be cast into their value types (although this will fail if they're null) or you can use the Value property (again it will throw an exception if it is null)
One thing which usually appears to be overlooked when using nullable types is the GetValueOrDefault() method which returns default(T) if the object is null.
As #Kyle Trauberman points out in the comment you can indeed compare it to null instead of checking HasValue. The type itself is a value type with overriden equality methods so that much as it will never be null itself it will return true when compared to null if it doesn't have a value.
A questionmark behind the declaration means that the variable is nullable.
int? can be null where as int can not.
Reference Nullable Types:
http://msdn.microsoft.com/en-us/library/1t3y8s4s(v=VS.100).aspx