Why is null not allowed for DateTime in C#? - c#

Why it is not allowed to assign null to a DateTime in C#? How has this been implemented? And can this feature be used to make your own classes non-nullable?
Example:
string stringTest = null; // Okay
DateTime dateTimeTest = null; // Compile error
I know that I can use DateTime? in C# 2.0 to allow null to be assigned to dateTimeTest and that I could use Jon Skeet's NonNullable class on my string to get a run time error on the assignment of stringTest. I'm just wondering why the two types behave differently.

DateTime is a value-type (struct), where-as string is a reference-type (class etc). That is the key difference. A reference can always be null; a value can't (unless it uses Nullable<T> - i.e. DateTime?), although it can be zero'd (DateTime.MinValue), which is often interpreted as the same thing as null (esp. in 1.1).

DateTime is a struct and not a class. Do a 'go to definition' or look at it in the object browser to see.
HTH!

The important distinction between ValueTypes and reference types is that value types have these "value semantics". A DateTime, Int32 and all other value types have no identity, an Int32 "42" is essentially indistinguishable from any other Int32 with the same value.
All value type "objects" exist either on stack or as a part of a reference type object. One special case is when you cast a value type instance to an Object or an interface - this is called "boxing", and it simply creates a dummy reference-type object which only contains the value that can be extracted back ("unboxed").
Reference types, on the other hand, have an identity. a "new Object()" does not equal any other "new Object()", because they are separate instances on the GC heap. Some reference types provide Equals method and overloaded operators so that they behave more value-like, eg. a String "abc" equals other "abc" String even if they are in fact two different objects.
So when you have a reference, it can either contain the address of a valid object, or it can be null. When value type objects are all-zero, they are simply zero. Eg. an integer zero, a float zero, Boolean false, or DateTime.MinValue. If you need to distinguish between "zero" and "value missing/null", you need to use either a separate Boolean flag, or, better yet, use the Nullable<T> class in .NET 2.0. Which is simply the value plus a Boolean flag. There's also support in the CLR so that boxing of a Nullable with HasValue=false results in a null reference, not in a boxed structure with false+zero, as it would if you were to implement this structure yourself.

DateTime is a value type, same as an int. Only reference types (like string or MyCustomObject) can be null. Reference types really store "references" to the objects location on the heap.
here's a article I found that explains it better. and here's the MSDN article on it

For a value-type to be null, there must be some value it can hold which would have no other legitimate meaning, and which the system will somehow know should be regarded as "null". Some value types could meet the first criterion without requiring any extra storage. If .net had been designed from the ground up with the concept of nullable values in mind, it could have had Object include a virtualIsLogicalNullproperty, and a non-virtualIsNullwhich would returntrueifthisis null and, otherwise invoke itsIsLogicalNullproperty and return the result. If .net had done this, it would have avoided the need for the quirky boxing behavior andstructconstraint ofNullable(an emptyNullablecould be boxed as an emptyNullable, and still be recognized asnull`).
By the time it was decided to provide support for nullable value types in .net framework 2.0, however, a lot of code had been written which assumed that the default values for things like Guid and DateTime would not be regarded as null. Since much of the value in nullable types lies with their predictable default value (i.e. null) , having types which had a null value, but defaulted to something else, would have added more confusion than value.

string is a class whereas DateTime is a structure. Thats why you cannot set it to null

Related

Is there a coalesce operator for parameters?

If F were "on" a, I could do this...
var obj = a?.F();
If F is not on a, I have to do this...
var obj = a == null ? null : MyFunc.F((A) a);
Or do I? Is there a more succinct way of skipping the method call if a parameter value is null?
The short answer is no, there's no succinct way to do that.
The slightly longer answer is still no, but there's an interesting language design point here. C# was designed by people with extremely good taste, if I say so myself, but it was designed over a very long period of time. Nowhere is this more obvious than with respect to its treatment of nullability.
In C# 1.0 we had a straightforward language in the tradition of C, C++, Java, JavaScript, and so on, where there are references and values, and references can be null. This has benefits; if it did not, Sir Tony would not have invented the null reference in the first place. But it has downsides: we have the possibility of null references, dereferencing null leads to program crashes, and there is an inconsistency between reference and value types: reference types have a natural "no value" value, and value types do not.
In C# 2.0 we added nullable value types, but nullable value types do not behave like nullable reference types. Of course nullable values types are not references, so you cannot "dereference" them, but if we squint a little, the .Value property looks a lot like "dereferencing", and it leads to a similar crash if the value is null. In that sense, they behave the same, but in other senses, they do not. Adding together two nullable integers does not crash if one of them is null; instead, the result is also null.
So at this point we have a contradiction built into the language:
Using a null value of a nullable value type usually automatically propagates the null, but using a null reference can crash.
And of course C# has then gone on to add a variety of features that make null references behave more like null values, like ?. and the related operations. There are also proposals for C# 8 that are very exciting, and will support "non nullable reference type" scenarios.
But the bolded text above is the fundamental problem you've pinpointed: the semantics of operators on nullable reference types are almost always "lift the non-nullable version of the operator to nullable types; if all the operands are non-null then the result is the same as the unlifted version; otherwise, the result is null". However, those semantics are not automatically extended to the . member access operator or the () call operator, regardless of whether the operands are nullable value types or nullable reference types. . can be lifted explicitly by ?. but the () operator does not get lifted to nullable semantics, ever.
Imagine a language like C# 1.0, but with Nullable<T> built in from the start, such that it applied to both reference and value types. In that world, you can see natural ways to implement generalized lifting, where if you have a method
class C { string M(double, int[]) }
and you call it with a Nullable<C> receiver, or Nullable<double> and Nullable<int[]> arguments, you automatically get the code that we build for you for nullable integer arithmetic: check whether the receiver or any arguments are null, and if they are, result in a null Nullable<string>. Otherwise, call the function normally and use the non-nullable result.
The C# compiler already implements these semantics for all user-defined operators declared on struct types; it would not be hardly any difficulty at all to extend those semantics to other kinds of methods. But we can't do it now; there are far too many backwards-compatibility issues to solve.
This design choice would also have the nice property that it would be a correct implementation of the "maybe monad".
But that's not the world we are in, and it's largely because these design considerations evolved over time, rather than being invented all at once. The next time you invent a new language, consider carefully how to represent nullability!

Why is Nullable type supported by CLR?

I heard that the addition of Nullable<T> type to C# 2.0 need to revise CLR(runtime) a little, is this change necessary? Could it make the same goal if a new Nullable<T> generic class was added only?
Nullable isn't a generic class as you indicate, Nullable<T> is generic (it has a type parameter, T). That's why Nullable<T> only arrived in C# 2.0: it came with the addition of generics to the CLR.
You could do the same thing with a general Nullable, but you couldn't do things like this:
int? myInt = 123;
int result = myInt.Value;
You would instead have to:
int result = (int)myInt.Value;
...and it might not be type-safe, by that I mean what if myInt.Value is a string? The generic version, Nullable<T>, would only allow an int into the Value property.
I don't completely understand what you're asking, though.. "why are generic classes useful"?
If I understand you correctly, you are asking why can't it just be Type introduced in the framework library? but instead the CLR need to be changed?
Well based on my understanding Nullable is a special type, not quite like other container type. First it is actually a value type - defined as struct, not a class. Separately it allows to be assigned a value of null (for value type, that is a special case), plus it support the use of '?' and operator '??' which is all new. The Nullable also become part of the Common type system. So I guess from these perspective, the specification, compiler and CLR will need to be changed.
There are only two reasons I know of for the special handling of Nullable<T>:
To allow a typecast from null Object reference to a Nullable<T> with HasValue = false.
To allow a Nullable<T> where HasValue is false, to compare equal to null.
Frankly, think it would have been better to let Nullable<T> box like any other value type, and define Nullable<T>.Empty as a value which may be compared against (for those cases where one might want to compare against a variable that might be null or might hold a value). To my mind, there's no reason why Object.Equals should report that an "int?" which is equal to null is equal to a "long?" which is also equal to null. The first should be viewed as an empty int-sized box, and the latter as an empty long-sized box.

What is the integer reference type in C#?

I'd like to have an integer variable which can be set to null and don't want to have to use the int? myVariable syntax. I tried using int and Int16 to no avail. Do I have to use int? myVariable?
I mentioned this because in Java there is both an 'int' type (a primitive) and 'Integer' (a reference type). I wanted to be sure that there isn't a built-in integer reference type that I could be using. I'll use 'int?' for what I'm doing.
For info, int? / Nullable<T> is not a reference-type; it is simply a "nullable type", meaning: a struct (essentially and int and a bool flag) with special compiler rules (re null checks, operators, etc) and CLI rules (for boxing/unboxing). There is no "integer reference-type" in .NET, unless you count boxing:
int i = 123;
object o = i; // box
but this creates an unnecessary object and has lots of associated other issues.
For what you want, int? should be ideal. You could use the long-hand syntax (Nullable<int>) but IMO this is unnecessarily verbose, and I've seen it confuse people.
Yes you should use nullable types
See Nullable
Nullable<int> Nullable<float>
or simply
int? float?
PS:
If you don't want to use ? notation or Nullable at all - simply use special structures for such a thing. For example DataTable:
var table = new DataTable();
table.Columns.Add('intCol',typeof(int));
var row = table.NewRow();
row['intCol'] = null; //
Nullable types are instances of the System.Nullable(T) struct.
Therefore int, int?, Nullable<int> are all value types, not reference types
Yes, it's the only way, as Int32/Int16/int is a primitive type (regardless of boxing/unboxing of these).
You will have to use a nullable type, i.e:
Nullable<int> or int?
The purpose of nullable type is, to enable you to assign null to a value type.
From MSDN:
Nullable types address the scenario where you want to be able to have a primitive type with a null (or unknown) value. This is common in database scenarios, but is also useful in other situations.
In the past, there were several ways of doing this:
A boxed value type. This is not strongly-typed at compile-time, and involves doing a heap allocation for every type.
A class wrapper for the value type. This is strongly-typed, but still involves a heap allocation, and the you have to write the wrapper.
A struct wrapper that supports the concept of nullability. This is a good solution, but you have to write it yourself.
You could use System.Nullable<int> if you hate ? so much.
Yes. That's why Microsoft added that. People were creating their own Nullable class so they included this pattern in .NET.
The <var>? syntax makes it nullable. If you dig a bit deeper, you'll see it's just a generic object that gets used.
If you want to do it like C++ you must use unsafe operations. Then, pointers like in C are available, but your code doesn't conform to CLR...
For using pure .NET without pointers, the ? is the way to go.

Confusion with NULLs in C#

I am always confused with the different ways of expressing nulls. There is the null reference type (aka "null"). Then I've seen that throughout my application, developers have used MinValue to represent nulls. Ex: Double.MinValue or DateTime.MinValue except for a String for which they use "null"
Then there is System.DBNull (and System.DBNull.Value - not sure what to use when). To add to the confusion, there are also System.Nullable and System.Nullable<T> namespaces.
Can someone help me clear this null confusion?
Thanks
Sure.
System.DBNull is a class that was (and still is) used by ADO.NET to represent a null value in a database.
null is actually a null reference, and in your application code any reference type should use null as its, well, null value.
The usage of MinValue for various primitive types (which, since they are value types cannot be assigned null) dates back to the dark days before C# 2.0, which introduced generics. Now the preferred method for representing a nullable primitive type is to use the Nullable<T> generic type, usually represented in shorthand with a question mark after the primitive type. For example, I could declare a nullable int variable named foo in C# as:
Nullable<int> foo;
or
int? foo;
Both are identical.
null is only valid for reference types: types that are a class rather than a structure.
.Net also has value types: int, double, DateTime, etc. Value types cannot be null, you so you normally compare those to their default value, which is very often type.MinValue, but might be something (consider Boolean, for example).
Nullable<T> is for when you have a value type that might genuinely be null. The default value (maybe MinValue) is also valid and you need to distinguish it from when the variable has not been assigned yet. In C#, you can use a ? with a value type as a short hand notation (for example: int?), but you're still creating the same Nullable<T>.
DBNull specifically refers to NULL values from a database. It's not the same thing as using null elsewhere in the language: it's only for talking to a database so you can know when a query returned a null value.
When using generics, you'll also see the default(T) construct used, where T is a type parameter. This allows you to set a type's default value without knowing whether that type is a reference type or a value type, much less what a specific value type's default value might be.
A Null value represents any reference type object that has not had its memory allocated yet.
The MinValue does not represent a Null, rather it is a property that is often used to represent the smallest possible constant value that a given value type can have.
The DBNull.Value class is a mapping of the Nulls returned/passed to a database.
The Nullable generic type enables you to assign Null values to a Value-type.
null for reference types in the
actual null value
Nullable, added in .NET 2.0 is a
way of expressing nulls for value
types, which by definition can not be
null.
Same with DateTime.MinValue -
DateTime is a value type, and can not
be null, so you can have a convention
that a well known value, like
DateTime.MinValue is treated as if it
was null. It also has other usages.
"MinValue"s were used with value types before nullable types came around in C# 2.0. So there is a lot of legacy code which uses the old style of knowing when a value type doesn't have a value. Nowadays it's much easier to use a DateTime? date = null than DateTime date = DateTime.MinValue. As far as DBNull goes, that is something that is required as an abstraction layer to databases, but you can avoid having to deal with it yourself by employing an ORM such as NHibernate or some such - you pretty much, from a app. development standpoint will only have to deal with built-in C# types.
MinValue is not null. It's MinValue. It is sometimes used "as null" by people using C# 1.0, which did not have nullable value types. Instead, they should use Nullable, ot DateTime?.
DBNull is a .NET value that is used to communicate with a database ("DB" null). The database concept of NULL means something different from the .NET null reference. In database terms, NULL means "unknown" or "absent".
Reference types (aka objects) can be set to null since reference type variables is just a pointer to the actual instance. Indicating the lack of an instance is easy since you can set the variable to null directly.
For value types this is a bit harder since a value type variable always contains a value.
Therefore, the use of Double.MinValue or DateTime.MinValue was somewhat valid in the pre-Nullable days. Back then there was no easy way of expressing the lack of a value in value types.
Now, with nullable types you can say:
double? d = null;
And thus you can also have value type variables containing null.
System.DBNull is a different story since it is directly tied to expressing the value "NULL" in datasets. This was introduced before nullable types which imo supersedes DBNull.
Most types in .NET are reference types, and null is "not a reference" which can be assigned to a variable or field to indicate there is no object.
All other types in .NET are value types. There is always a value with a value type, so no ability to indicate "no value". Therefore an implementation may define specific special values to indicate this. Often the value type's MinValue (constant) field is used for this. So using DateTime.MinValue for a date of birth can indicate "not known" or "not applicable" (e.g. for a corporate entity).
DbNUll exists to express RDBMS's meaning of NULL which is a little different to .NET's. In most cases this will be translated to null or similar.
Finally, Nullable<T> is a wrapper for value types to more directly express "not known", and is generally a better option than using MinValue, but was added in .NET 2, so older designs may have started using MinValue before Nullable<T> is available.
the best way for tou to understand this different null values is to try them and see what the use of each one but to make things simple here is some guideline
null can be used only on reference types like collections and custom classes (string is special)
DBNull is for null values that came out of the db query.
because we cant assign null to a decimal or double we assign them with the MinValue property (they are value objects)
Nullable is a way for the developer to assign null values to value objects like decimal,
Nullable<int> is same as int?
i hope i helped you understanding the differences.
The important difference here is that between value types and reference types.
Value types represent directly a certain value, whereas reference types point to a memory location that should represent a value. When a a reference type actually does not point to a memory location with valid contents, the reference is Null.
Since value types are direct representations of value, they cannot be null. However, it might be the case that a actual value of a value type is unknown. For this case, .Net provides the Nullable types construct. When such a construct is not available, however, people tend to use special or default values, such as MinValue.
When communicating with databases, a lot of things we expect to be value types can actually be Null, since that it the way the database handles unknown values. This can also be solved by the Nullable types, but these were not always available. That's why DBNull exist, to deal with a possible null in a database.

Should I use default(Foo), Foo.Empty, or null?

So C# now allows you to use default(Foo) to get a recognized "not filled in yet"/empty instance of a class -- I'm not sure if it is exactly the same as new Foo() or not. Many library classes also implement a Foo.Empty property, which returns a similar instance. And of course any reference type can point to null. So really, what's the difference? When is one right or wrong? What's more consistent, or performs better? What tests should I use when checking if an object is conceptually "not ready for prime time"? Not everybody has Foo.IsNullOrEmpty().
default(Foo) will return null when Foo is a class type, zero where Foo is a value type (such as int), and an instance of Foo with all fields initialized to their respective default() values where Foo is a struct. It was added to the language so that generics could support both value and reference types - more info at MSDN
Use default(Foo) when you're testing a T in the context of SomeClass<T> or MyMethod<T> and you don't know whether T will be value type, a class type or a struct.
Otherwise, null should mean "unknown", and empty should mean "I know this is empty". Use the Foo.Empty pattern if you genuinely need an empty - but non-null - instance of your class; e.g. String.Empty as an alternative to "" if you need to initialize some variable to the empty string.
Use null if you know you're working with reference types (classes), there's no generics involved, and you're explicitly testing for uninitialized references.
When you know the actual type involved, or if you've got a type parameter constrained with ": class" it's simplest to use the known value (null, 0 etc).
When you've just got a type parameter which is unconstrained or constrained other than to be a reference type, you need to use default(T).
default(Foo) works for both value types and reference types. New Foo(), null and Foo.Empty() do not. This makes it a good choice for use with generic types, for example, when you may not know which you're dealing with. But in most reference-type cases, null is probably good enough.

Categories