views:

556

answers:

7

I have seen this in legacy code and in some .NET open source projects. I can't imagine a reason to do this. Just using "null" seems so much easier to me.

Example:

public class Category
{
   int parentID;

   bool HasParent
   {
      get
      {
          return parentID != -1;
      }
   }
}

versus

public class Category
{
   int parentID;

   bool HasParent
   {
      get
      {
          return parentID != null;
      }
   }
}
+3  A: 

See http://stackoverflow.com/questions/585219/why-dont-we-have-two-nulls

vartec
That question has nothing to do with this one...
Gavin Miller
Actually, it does. Because vartec is suggesting that the developers in THIS question maybe using both 'null' and "magic numbers" to apply to the different cases that have no valid results.
Of course it does. It shows that some ppl feel they need to differentiate between "no value" and "never set".
vartec
You guys are right - I can see that now with the edits.
Gavin Miller
A: 

Have you really looked into the application to see? As long as the magic number is held in a single place with a descriptive name it can be quite useful.

Andrew Hare
Yes, they are held in a single place with a discriptive value, like Null.NullInteger and Null.NullDate, but I wasn't able to figure out why it is usefull
Paco
Then it is not a "magic value" at all - magic values are literals in the source code that have no context and therefore ambiguous meaning.
Andrew Hare
I consider this a magic value because you have to know it is not just an integer or date, but you must compare it with the Null.NullObject to know what it means. You can't know that you have to compare it with the nullobject before using the value.
Paco
+3  A: 

Having a null object can cause exceptions to be thrown, whereas error codes (like a "-1" failure case) would not throw an exception.

This can be critical in languages or applications which do not handle exceptions well.

+2  A: 

Working on big datawarehouses, i sometimes uses the 0 value instead if null, to insert a non null value in my cube. i always have a 0 id corresponding to 'Unknown' value in all dimensions, so i have a cube with no null values.

the main interest in it is to have simplier and more efficient queries

chburd
+2  A: 

These are often habits developed when programming in C. Many a C programmer would be horified at the waste of nullable ints, which at the very least require an entire extra bit, and possibly even a pointer. This is especially bad when you know the value is going to be positive and you have the entire space of negative values to use for flags. -1 can mean not set, -2 can mean that parentId doesn't even make sense in the context of this node, -3 can mean that the node had a parent that couldn't handle the work and left on a drinking binge and was never seen again, etc...

In the C# world the cleaness of nullable ints (and their easy integration with RDMS's) along with computers with 2GB+ of RAM means that the old C habits are slowly dying, but old habits die hard.

Eclipse
+1  A: 

Nullable value types are not available in every language/environment; They were added to .Net 2.0. If your legacy code is .Net based and was started using the 1.1 framework, then your answer is that null wasn't an option at the time.

Chris Shaffer
+8  A: 

Because to have a "null" value, the type must be nullable. This works fine for reference types (any class you define and the standard library), and if you look you'll see that people do use null whenever they have a reference object with no value

Employee employee = Employees.Find("John Smith");
if(employee == null) throw new Exception("Employee not found");

The issue comes when you use the value types like int, char or float. Unlike reference types, which point to a block of data somewhere else in memory, these values are stored and manipulated inline (there is no pointer/reference).

Because of this, by default, the value types do not have a null value. In the code you provided, it is impossible for parentID to be null (I'm actually surprised this even got by your compiler - Visual Studio 2008 and probably 2005 will draw a green underline and tell you that the statement is always false).

In order for an int to have a null value, you need to declare it as nullable

int? parentID;

Now parentID can contain a null value, because it is now a pointer (well "reference") to a 32 bit integer, instead of just a 32bit integer.

So hopefully you understand why "magic values" are often used to represent null with the basic types (value types). It is simply a lot of trouble, and often a large performance hit (lookup what boxing/unboxing is), to store these value types as a reference to the value in order to allow them to be null.

Edit: For further reference about boxing/unboxing (what you need to have an int==null), see the article at MSDN:

Boxing and Unboxing (C# Programming Guide)

Performance

In relation to simple assignments, boxing and unboxing are computationally expensive processes. When a value type is boxed, a new object must be allocated and constructed. To a lesser degree, the cast required for unboxing is also expensive computationally. For more information, see Performance.

David
I can't imagine a case where this very small performance gain is critical.
Paco
The overhead is *not small* - you're talking about adding boxing/unboxing operations to the *fundimental* data types and operations. A benchmark doing a conditional integer addition operation runs 9 times slower when the values are nullable because of the boxing overhead. Try it for yourself.
David
I know how long it takes, but I don't believe in optimizing O(N) algorithms.
Paco