Nullable types in .NET 2.0 are a great asset for many developers. I use them all the time in my current project. However there are some things that you should be aware of. Because they can be filled in or can be null you should perform some extra checks in order to get your code to behave like you would expect it.
1 <%@ Page Language="C#"%>
2
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
5 <script runat="server">
6
7 protected void Page_Load(object sender, EventArgs e)
8 {
9 DateTime startDate = newDateTime(2004, 5, 23);
10
11 // Using a nullable DateTime can represent an occurance that doesn't expire.
12 // In a database, like SQL Server, you can have this field set to NULL.
13 DateTime? endDate = null;
14 DateTime toCheck = newDateTime(2006, 6, 13);
15
16 // First example: this test will fail because we check
17 // a normal DateTime against a nullable DateTime without
18 // replacing it with something to check against when it's null.
19 // Note however that this code compiles! It's only not working out
20 // in a functional logic way because it doesn't do what we would expect.
21 if (startDate <= toCheck && toCheck < endDate)
22 LabelEndDateNull.Text = true.ToString();
23 else
24 LabelEndDateNull.Text = false.ToString();
25
26
27 // Second example: now we're checking, and replacing it with an appropriate
28 // value in case it's null, so the test will pass as expected.
29 // The trick here is to use the GetValueOrDefault() method on a Nullable type
30 // to replace it with a default value in case it's null.
31 if (startDate <= toCheck && toCheck < endDate.GetValueOrDefault(DateTime.MaxValue))
32 LabelEndDateNullButWithGetValueOrDefaultUsage.Text = true.ToString();
33 else
34 LabelEndDateNullButWithGetValueOrDefaultUsage.Text = false.ToString();
35
36 // Third example: this one's exactly the same as the previous, second, example.
37 // Only here I'm applying the great ?? operator available in C# 2.0.
38 if (startDate <= toCheck && toCheck < (endDate ?? DateTime.MaxValue))
39 LabelEndDateNullButWithCheck.Text = true.ToString();
40 else
41 LabelEndDateNullButWithCheck.Text = false.ToString();
42
43
44 // Fourth example: fill up the nullable DateTime with some actual value:
45 endDate = newDateTime(2007, 1, 1);
46
47 // We can see, this is easier when done debugging the code, that the enddate
48 // now has some actual value and the test will pass.
49 if (startDate <= toCheck && toCheck < (endDate ?? DateTime.MaxValue))
50 LabelEndDateNotNull.Text = true.ToString();
51 else
52 LabelEndDateNotNull.Text = false.ToString();
53 }
54
55 </script>
56
57 <html xmlns="http://www.w3.org/1999/xhtml">
58 <head runat="server">
59 <title>Untitled Page</title>
60 </head>
61 <body>
62 <form id="form1" runat="server">
63 <div>
64 Enddate = null:
65 <asp:Label ID="LabelEndDateNull" runat="server"></asp:Label>
66 <br/>
67 <br/>
68 Enddate = null but with GetValueOrDefault method:
69 <asp:Label ID="LabelEndDateNullButWithGetValueOrDefaultUsage" runat="server"></asp:Label>
70 <br/>
71 <br/>
72 Enddate = null but with ?? check:
73 <asp:Label ID="LabelEndDateNullButWithCheck" runat="server"></asp:Label><br/>
74 <br/>
75 EndDate != null:
76 <asp:Label ID="LabelEndDateNotNull" runat="server"></asp:Label></div>
77 </form>
78 </body>
79 </html>
Take a look at the comment in the code, or better yet: debug it on your own dev machine, to see the subtle difference between the first and second example. The third example's just the same as the second but uses the ?? operator, the one that I prefer in my code because its shorter. The ?? operator, or null coalescing operator, is only available in C# 2.0.
Grz, Kris.