tags:

views:

323

answers:

5

Using .NET 3.5 and C# 3.0,

IList list = new List<bool?>();
list.Add(null);

This throws an ArgumentException, which just feels wrong.

List<bool?> list = new List<bool?>();
list.Add(null);

Works perfectly.

Is this a bug in Microsoft's code, then?

An example of how to produce this kind of error in a real-life situation:

new JavaScriptSerializer().Deserialize<List<bool?>>("[true, false, null]");
A: 

You're mixing the Generic List<T> with the non-generic IList. List<T> inherits from IList<T> and not from IList.

Tony
I assume you meant your first IList to be IList(T)From http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx,public class List(T) : IList(T), ICollection(T), IEnumerable(T), IList, ICollection, IEnumerable(changed angle brackets to parentheses)It inherits from both, properly.
ckknight
+10  A: 

Yes, it is. See http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/abc99fb5-e218-4efa-8969-3d96f6021cee/ for other reports. Basically when you access the List<bool?> through its weak-typed IList implementation, it does some type checking before trying to add the item to the internal storage -- and it gets this type checking wrong for nullable types.

itowlson
The answer is "yes that's actually a bug" for once instead of of "no, you screwed up here..." savoring the moment... :D
CrazyJugglerDrummer
A: 

Ha! That's a funny one. I believe it has to do with the idea that the nullable bool is, strictly speaking, implemented as a struct and IList expects an object, and maybe it's expecting to box a bool or something. Jon Skeet where are you? We need you! (taps ruby slippers 3 times)

Dave Markle
+3  A: 

It's "By Design" and explicitly so. The reason why is that List<T> has an explicit implementation of IList. It filters values passed to the various methods to do a bit of null checking. The logic essentially is the following

if (default(T) != null && value == null) { throw ... }

In this case the default of a value type (and nullable is a value type) is not null hence it's not allowed.

JaredPar
default(bool?) == (bool?)null, though.
ckknight
+1  A: 

When you call the Add method on the IList with a null value, it's a null reference that you are passing to the method, not a nullable value. The null reference can't be converted into a nullable value.

The Add method expects something that contains a bool or a bool?. As you can't box a null value, you can't create an object that is possible to use to add a null value to the IList.

If you use the generic interface IList<bool?> instead, there is no problem adding the value:

IList<bool?> list = new List<bool?>();
list.Add(null);
Guffa
Sadly, in this case, that won't work. An example of this in action is to use the new JavaScriptSerializer().Deserialize<List<bool?>>("[true, false, null]")
ckknight