The generic Nullable type in Whidbey and the C# language features it supports are great. They've enabled me to eliminate gobs of code and simplify things incredibly. But, Joe Duffy's latest request for feedback on some of the "syntactic suger" on this feature brings up some interesting points. He shows us several different equality tests against a nullable value type and asks if the results are intuitive. I suspect it's a loaded question, because they are not. Someone with a good understanding of the framework can fairly easily guess the outcome, but deep down I think they would have to admit it's not ideal.
What it boils down to is what is the purpose of the generic Nullable type. I originally viewed it as helping to code against scenarios where values can be null like databases. Without nullable value types, you frequently have to check to see whether you're dealing with a null value, and carry around alot of state information, and Nullable simply does that for you. I think some of the designers of this feature see it much more broadly as a concept to unify the type system in a more performant way than simply being able to cast to object. This requires some special casing, as is evident by the special case for type parameter constraints on generic types. Specifying struct will not allow you to use a generic Nullable, despite the fact that it is a value type. The problem is that the special casing stops short of completely abstracting the concepts.
The problem can readily be seen in Joe's second two tests, boxing a valueless "int?", and using the equality operator "==" against a generic argument that is instantiated as "int?" and has no value. Both do the opposite of what you might expect if you don't think through it first. Both do not equate to null.
I pondered this for quite a while before deciding how bad this was (and I'm still not exactly sure). For me, this is no problem since I understand the issues at work. For the future of the language, the outcome is not so clear. The real question is, "Is a value-less value type different from a null reference?" I don't think it should be. If you cast a null string reference to object, does it retain its identity as a string? No. Can you cast it back to a string reference? Yes. So, should there be a difference in behavior with nullables? I'll let you decide. Then there is the issue of how (and if) to effectively fix it. Adding a conversion from Nullable to object that makes it a null reference instead of a boxed value type might do it, at least for the boxing scenario. That's probably a pretty naive solution. I haven't really thought that through. For the generic situation, Nullable seems to be already special cased to some degree. It doesn't seem like it would be too much of a stretch to generate appropriate code for Nullable. The big problem here is that since this happens at JIT time, it's no longer a C# feature. Unfortunately, it's likely too late to address the issue in the in any real way, and that will likely set too much precedence to change it in the future if a solution could be reached. Perhaps some FxCop rules could find these types of situations and at least flag them so they could be looked at more closely.
Remember Me
Page rendered at Monday, January 05, 2009 11:56:35 PM (Pacific Standard Time, UTC-08:00)
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.