Do C# Nullable variables still function as value types? - c#

If I declare a nullable (either via Nullable or the ? symbol) variable from a value type, does it still respect the rules of value types (i.e. pass by value by default, deallocated when it falls out of scope, not when the garbage collector runs) or does it turn into a reference type since it's actually of type Nullable?

The documentation is here:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx
As you can see, the documentation describes this as the "nullable structure", indicating that it is a value type. Also, the documentation gives the first lines of the declaration of the type:
public struct Nullable<T> where T : struct, new()
again showing that the type is a value type.

Yes, System.Nullable is a generic Struct, ie value type.

Nullable value types are essentially just a struct wrapper around a value type which allows them to be flagged as null.
something like this:
struct Nullable<T>
{
public T Value;
public bool HasValue;
}
I believe it's actually more complex than that under the hood, and the compiler does lots of nice stuff for you so you can write for example if(myInt == null). But yes, they are still value types.

Related

Is it possible to cheat C# compiler to box Nullable<T> struct ant not its value?

Well, the question may seem odd. And it really is.
Yet I strongly believe that such hacks help in understanding the language and .net platform.
It is how C# compiler treats nullable types implies this question.
Nullable<T> is a struct. But compiler boxes not this struct but the value it holds or just null reference.
It is also intersting how unboxing will work in the case of the boxed Nullable.
Nullable<int> myInt = boxedStruct as Nullable<int>;
here I meen that boxedStruct is not a boxed int but the whole struct.
Well, may be Nullables are treated differently at CLR level because I cannot understand the ouptut of the program below.
class Program
{
public static bool? Property { get; set; }
static void Main(string[] args)
{
Property = true;
var valueType = typeof (Program).GetProperty("Property").GetValue(null).GetType();
var propType = typeof (Program).GetProperty("Property").PropertyType;
Console.WriteLine("Value's type '{0}' is the same as type of the property '{1}' - '{2}'", valueType, propType, valueType == propType);
Console.ReadKey();
}
}
The output:
Value's type 'System.Boolean' is the same as type of the property
'System.Nullable`1[System.Boolean]' - 'False'
Update:
Here what specification (ECMA 335) says:
I.8.2.4 Boxing and unboxing of values ... If the value type
is a nullable type—defined as an instantiation of the value type
System.Nullable—the result is a null reference or bitwise copy of
its Value property of type T, depending on its HasValue property
(false and true, respectively).
So if I understand this correctly. Nullable<T> strcut cannot be boxed in .Net Framework and it's not just impossible with C# compiler but with CLR as well.
I am conjecturing that the question you are trying to ask is:
Can you box a Nullable<int> value without producing a null reference or a boxed int value, but instead an actually boxed Nullable<int>?
No.
Is it possible to cheat C# compiler to box Nullable<T>?
No, as it is not the compiler who does the boxing, it is the CLR. Yes, the boxing of nullable types is specifically handled in the CLR itself.
So is there a way to box a nullable struct without this special handling? Also no.
But it is possible to box another structure that looks like Nullable<T> (ensuring it has the appropriate layout) and with the help of undocumented keywords and memory hacking trick the CLR into thinking the boxed object is actually of Nullable<T>.Beware! This code should be used only for educational purposes. I can't guarantee it will work on other platforms or work at all in different conditions, because it relies on the underlying layout of managed objects.
public static unsafe object BoxNullable<T>(T? nullable) where T : struct
{
object scam = new NullableFake<T>(nullable);
TypedReference tr = __makeref(scam);
IntPtr typehandle = typeof(Nullable<T>).TypeHandle.Value;
IntPtr* trstruct = (IntPtr*)&tr;
**((IntPtr**)trstruct[0]) = typehandle;
return scam;
}
struct NullableFake<T> where T : struct
{
public readonly T? Value;
public NullableContainer(T? nullable)
{
Value = nullable;
}
}
The NullableFake<T> structure has the same layout as Nullable<T>, so it is safe to use it for boxing. TypedReference is used for obtaining a pointer to the variable (that contains a pointer to the object), exposing the object itself. The first value in the object's memory layout is a pointer to the object's type. Overwriting it results in the CLR thinking the type is different.
I don't know any safer way to do it.

Why can an int? set to null have instance properties?

I'm curious as to why the following code works (run under the VS debugger):
int? x = null;
null
x.HasValue
false
If x is indeed null, what instance does HasValue refer to? Is HasValue implemented as an extension method, or does the compiler special case this to make it magically work?
Because x isn't a reference type. The ? is just syntactic sugar for Nullable<T>, which is a struct (value type).
int? is actually a structure Nullable<int>. Hence this, your x cannot be null, because it is always instance of a structure.
Hand-waving answer: Nullable structs are magic.
Longer answer: Null is not actually what is represented by the value. When you assign null to a nullable struct, what you will see happen behind the scenes is different.
int? val = null; // what you wrote
Nullable<Int32> val = new Nullable<Int32>(); // what is actually there
In this case, an instance of the struct is created that has the T Value set to a default value and the bool HasValue property set to false.
The only time you will actually obtain a null reference from a Nullable<T> is when it is boxed, as a Nullable<T> boxes directly to T or null, depending upon if the value is set.
There are several meanings to null.
One in programming languages which present variables and memory in a pointer-based manner (which includes C#'s references though it hides some of the details) is "this doesn't point to anything".
Another is "this has no meaningful value".
With reference types, we often use the former to represent the latter. We might use string label = null to mean "no meaningful label. It remains though that it's still also a matter of what's going on in terms of what's where in memory and what's pointing to it. Still, it's pretty darn useful, what a shame we couldn't do so with int and DateTime in C#1.1
That's what Nullable<T> provides, a means to say "no meaningful value", but at the level below it's not null in the same way a null string is (unless boxed). It's been assigned null and is equal to null so it's logically null and null according to some other semantics, but it's not null in the "doesn't point to anything" implementation difference between reference and value types.
It's only the "doesn't point to anything" aspect of reference-type null that stops you from calling instance methods on it.
And actually, even that isn't strictly true. IL let's you call instance methods on a null reference and as long as it doesn't interact with any fields, it will work. It can't work if it needs (directly or indirectly) those fields since they don't exist on a null refernce, but it could call null.FineWithNull() if that method was defined as:
int FineWithNull()
{
//note that we don't actually do anything relating to the state of this object.
return 43;
}
With C# it was decided to disallow this, but it's not a rule for all .NET (I think F# allows it, but I'm not sure, I know unmanaged C++ allowed it and it was useful in some very rare cases).
When using int? x = null then x is assigned a new instance of Nullable<int> and ist value is set to null.
I don't exactly know the internals but I would assume that the assignment operator itself is somewhat overloaded.
A nullable type isn't actually null since it still doesn't get around the fact that value types can't be null. It is, instead, a reference to the Nullable<> struct (which is also a value type and can't be null).
More information here.
Basically, you're always referring to an instance of something when you use a nullable type. The default information returned by that reference is the stored value (or null if there is no stored value).
Nullable isn't really a reference type, and its instance methods are one of the places where this shows up. Fundamentally, it is a struct type containing a boolean flag and a value of the type it is a nullable of. The languages special-case various operators [to be lifting, or to consider (bool?)null false in some cases] and the null literal, and the runtime special-cases boxing, but apart from that it's just a struct.
It's a completely new type. Nullable is not T.
What you have is a generic class something like this:
public struct Nullable<T>
{
public bool HasValue { get { return Value != null; } }
public T Value { get; set; }
}
I'm sure there's more to it (particularly in the getter and setter, but that's it in a nutshell.
The nullable type (in this case: nullable int) has a property of HasValue which is boolean. If HasValue is True, the Value property (of Type T, in this case, an int) will have a valid value.

Are nullable value types just wrappers around the regular value type?

The reason I ask is that you can cast a nullable type to a regular type with the Value property. That makes me think that the regular type is just wrapped up in the nullable type.
Yes, it is a generic struct:
public struct Nullable<T> where T : struct, new()
This is probably more confusing if you've only seen the T? syntax - but that is just syntactic sugar, the compiler is changing it to Nullable<T>.
Source: http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx , http://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx
Yes - 'Nullable<T> Structure':
Represents an object whose underlying
type is a value type that can also be
assigned null like a reference type.
[BTW, if your curious you can use Reflector to 'look under the hood']
According to MSDN "Nullable types are instances of the System.Nullable<T> struct. A nullable type can represent the correct range of values for its underlying value type, plus an additional null value"

C# struct, how to assign a null value?

I have a list:
List<int, SomeStruct>
For some reason, it is not allowing me to assign null values to it. What do I do if I want to have no struct associated?
Use nullable types:
List<int, SomeStruct?>
You can't assign null to an element of the list because structs are value types, while null means an empty pointer, and so can only be assigned to reference type variables.
Also note that List as you're using it doesn't exist in .NET! Perhaps you want Dictionary?
In C# a struct is a 'value type', which can't be null.
If you really, really need to be able to null this, then make it into a 'nullable' type by adding a trailing question mark.
You should probably look into the details of this more first, though - it's quite likely you don't really want a 'struct' at all, but would be better with a 'class'.
Unless you have defined a custom generic collection, List<T, U> doesn't exist in the System.Collections.Generic namespace. Did you rather mean Dictionary<TKey, TValue>?
You can use Nullable types: Using Nullable Types (C# Programming Guide).
As for any ValueType, you need to specify explicitly that you will allow null values for your type. You can do so by concatenating the '?' character with your type name, or by marking it as Nullable, where T is the name of your structure.
All of the existing answers here are correct: in C# struct is a value type and cannot be null.
However some struct implementations (but definitely not all) follow a convention where the default/empty value is stored in a Empty static field. Sometimes there is also an IsEmpty property:
// System.Guid
public struct Guid : IFormattable, IComparable, IComparable<Guid>, IEquatable<Guid>
{
public static readonly Guid Empty;
...
}
// System.Drawing.Point
public struct Point
{
public static readonly Point Empty;
public bool IsEmpty { get; }
...
}
If the struct has an Empty field or IsEmpty property, then you can use it to test if the struct variable is Empty instead of null. Otherwise use a nullable wrapper as the other answers state.
If you are the programmer of the struct, strongly consider adding an Empty field and IsEmpty property if appropriate.

What C# data types can be nullable types?

Can someone give me a list, or point me to where I can find a list of C# data types that can be a nullable type?
For example:
I know that Nullable<int> is ok
I know that Nullable<byte[]> is not.
I'd like to know which types are nullable and which are not. BTW, I know I can test for this at runtime. However, this is for a code generator we're writing, so I don't have an actual type. I just know that a column is string or int32 (etc).
All value types (except Nullable<T> itself) can be used in nullable types – i.e. all types that derive from System.ValueType (that also includes enums!).
The reason for this is that Nullable is declared something like this:
struct Nullable<T> where T : struct, new() { … }
A type is said to be nullable if it can be assigned a value or can be assigned null, which means the type has no value whatsoever. Consequently, a nullable type can express a value, or that no value exists. For example, a reference type such as String is nullable, whereas a value type such as Int32 is not. A value type cannot be nullable because it has enough capacity to express only the values appropriate for that type; it does not have the additional capacity required to express a value of null.
The Nullable structure supports using only a value type as a nullable type because reference types are nullable by design.
The Nullable class provides complementary support for the Nullable structure. The Nullable class supports obtaining the underlying type of a nullable type, and comparison and equality operations on pairs of nullable types whose underlying value type does not support generic comparison and equality operations.
From Help Docs
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx
It can be any value type including struct, it cannot be a reference type, as those are inherently nullable already.
Yes:
Int32
double
DateTime
CustomStruct
etc.
No:
string
Array
CustomClass
etc.
For more information, see MSDN: http://msdn.microsoft.com/en-us/library/2cf62fcy(v=VS.80).aspx
Any data type can be nullable.
Nullable works for you because normal int is not nullable, so the conversion to nullable int is necessary.
Nullable<int[]> not works because int[] is already a nullable type.
Nullable does not support types that are already nullable.
Note, that you need to convert a type to be nullable only if he is not already a nullable type.
Value types are not nullable, value types are int, float, double, long etc, as well as structs you create.
While reference types, for example, are already nullable (classes for example).
You can use the ? operator to make the type to be a nullable type.
Note, that even tho it's not a good practice if you would use the question mark operator on a type that is already nullable it will not raise an error.
int? myNullableVar = null;
int[]? MyNullableArr = null; //not necessary but does not raise an error

Categories