Which is preferred: Nullable<>.HasValue or Nullable<> != null?
I always used (a) Nullable<>.HasValue
because I liked the semantics. However, recently I was working on someone else's existing code base where they used (b) Nullable<> != null
exclusively instead. Is there a reason to use one over the other, or is it purely preference?
(a)
int? a;
if (a.HasValue)
...
(b)
int? b;
if (b != null)
...
The compiler replaces null comparisons with a call to HasValue
, so there is no real difference. Just do whichever is more readable/makes more sense to you and your colleagues.
我更喜欢(a != null)
以便语法与引用类型相匹配。
I did some research on this by using different methods to assign values to a nullable int. Here is what happened when I did various things. Should clarify what's going on. Keep in mind: Nullable<something>
or the shorthand something?
is a struct for which the compiler seems to be doing a lot of work to let us use with null as if it were a class.
As you'll see below, SomeNullable == null
and SomeNullable.HasValue
will always return an expected true or false. Although not demonstrated below, SomeNullable == 3
is valid too (assuming SomeNullable is an int?
).
While SomeNullable.Value
gets us a runtime error if we assigned null
to SomeNullable
. This is in fact the only case where nullables could cause us a problem, thanks to a combination of overloaded operators, overloaded object.Equals(obj)
method, and compiler optimization and monkey business.
Here is a description of some code I ran, and what output it produced in labels:
int? val = null;
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
Ok, lets try the next initialization method:
int? val = new int?();
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
All the same as before. Keep in mind that initializing with int? val = new int?(null);
int? val = new int?(null);
, with null passed to the constructor, would have produced a COMPILE time error, since the nullable object's VALUE is NOT nullable. It is only the wrapper object itself that can equal null.
Likewise, we would get a compile time error from:
int? val = new int?();
val.Value = null;
not to mention that val.Value
is a read-only property anyway, meaning we can't even use something like:
val.Value = 3;
but again, polymorphous overloaded implicit conversion operators let us do:
val = 3;
No need to worry about polysomthing whatchamacallits though, so long as it works right? :)
链接地址: http://www.djcxy.com/p/30408.html上一篇: 字典可以一样快吗?