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 anull
value in a database.null
is actually anull
reference, and in your application code any reference type should usenull
as its, well,null
value.The usage of
MinValue
for various primitive types (which, since they are value types cannot be assignednull
) 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 theNullable<T>
generic type, usually represented in shorthand with a question mark after the primitive type. For example, I could declare a nullableint
variable namedfoo
in C# as:Nullable<int> foo;
or
int? foo;
Both are identical.
Adam Robinson : Thanks for the formatting! ;)annakata : nicely done - clear and informative -
"
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 aDateTime? date = null
thanDateTime 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".
Tracker1 : DBNull in database terms means the same as null in C# terms, it's only that when .Net 1.x came out there was no nullable type available, as Generics were introduced in version 2.John Saunders : Sorry, that's not the case. NULL in a Relational database means "unknown" or "no information". Think of an OUTER join with no matching row in the second table - columns from that table will be returned as NULL, meaning not present. -
- 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.
Cerebrus : I would contest the last point... DBNull is not replaced by the Nullable type.Joel Coehoorn : DateTime.MinValue isn't just convention. It's the value of a DateTime variable if nothing has been assigned to it yet.Samuel : @Cerbrus: I would also contest the last point. DBNull doesn't represent null in C#, but in the database. While Nullable is null in C#. -
A
Null
value represents any reference type object that has not had its memory allocated yet.The
MinValue
does not represent aNull
, 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.
-
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 usingDateTime.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 ofNULL
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 usingMinValue
, but was added in .NET 2, so older designs may have started usingMinValue
beforeNullable<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.
-
null
is only valid for reference types: types that are aclass
rather than astructure
.- .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 sameNullable<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.
-
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.
-
I think, and this is honestly not meant offensive at all, that if you are struggeling with the difference between value types and reference types and MinValues and null-references, some studying is in order before continuing to program at all!
Take any decent C# or .net studying book and start studying, I'm sure you will not regret it! Because not knowing these basic things for sure implies you're missing a lot!
Courage, and don't shoot the messenger!
0 comments:
Post a Comment