A - DAL返回Model,SqlDataReader取字段内容赋值给Model属性时
model.a = reader.IsDBNull(6) ? null : (int?)reader.GetInt32(6);
用reader的IsDBNull(int i)方法来判断读取到的数据库字段内容是否为空值,如果是,则赋给Model属性null值(DBNull.Value是system命名空间下的DBNull类的一个静态只读字段,和null不是一个类型),如果不为空,则根据既知的字段类型返回数值,但三元运算符"?"要求冒号两边的数据类型可以隐式转换,因此返回值类型的getint32方法的返回值必须再给它强转为一个可空值类型,也就是"int?".
再如:
model.b = reader.IsDBNull(5) ? null : (DateTime?)reader.GetDateTime(5);
model.c = reader.IsDBNull(4) ? null : (bool?)reader.GetBoolean(4);
model.c = reader.IsDBNull(4) ? (bool?)null : reader.GetBoolean(4);//这样也可以,同样还是只考虑类型上隐转的可行性,不必考虑运行时可能出现的赋值异常
person.Height = txtHeight.Text.Trim() == string.Empty ? null : (object)Convert.ToInt32(txtHeight.Text.Trim());//这样也会报错:无法将类型“object”隐式转换为“int?”。存在一个显式转换(是否缺少强制转换?) ,person.Height是一个可空值类型int?,只能赋值一个null或者int类型,不能赋值object,所以(object)Convert.ToInt32(txtHeight.Text);需要写成(int?)Convert.ToInt32(txtHeight.Text);,冒号两边的类型兼容性是一方面,同时还要注意与被赋值变量类型的兼容.
B - DAL由Model字段向SQL语句参数传值时
new SqlParameter("@height",model.Height==null?DBNull.Value:(object)model.Height),
new SqlParameter("@gender",model.Gender==null?DBNull.Value:(object)model.Gender)
Model对象属性中的空值为null,而sql语句(sqlcommand对象)参数赋空值是要赋DBNull.Value进去,这里就又涉及到了三元运算符?的冒号两边数据类型必须可隐式转换问题,我做了个小测试:
object o;
o = DBNull.Value;
但是bool? b = (bool?)o;一样会在运行时出错.
=======
DBNull a = null;
DBNull b = (DBNull)null;
以上代码均不报错,所以默认情况下,null是可以隐式转换为DBNull类型的,而object必然是DBNull的基类,所以DBNull类型的值可以赋给基类型object,所以对于三元运算符?,把右边的可空值类型再进一步强转为object类型(作为根类必然可以强转),就可以实现DBNull向它隐式转换了.
但是实验中我发现new SqlParameter("@gender",model.Gender==null?(object)DBNull.Value:model.Gender)这样也是可以的.所以继续测试:
object o;
DBNull a = null;//这里必须手动赋个初值,否则不能使用
o = (object)a;
bool? b = (bool?)o;//有点拆箱和里氏转换的感觉,这里我认为只是语法检测上的正确,实际上能不能转换成功,那只有运行时推断出类型时才知道结果,此时b的值为null.
这说明语法上讲这样也是可行的,运行过程中也不会出错,毕竟这样做的话,参数已经不会被赋入null值了,
但是!如果我们上面把DBNull a = DBNull.Value,在运行到bool? b = (bool?)o;时,编译时就会出错这说明从根本上还是无法转换的.
因此我认为两边加object强转都可以:一种是DBNull与object之间隐转,一种是bool?与object之间隐转,此处只考虑类型是否可隐转即可,运行时的赋值异常在此处并不会遇到.
总之一句话,在这种情况下的三元运算逻辑中,DBNULL.Value和null的处理只需关注类型可隐转以及冒号两边的数据类型是否可以赋值给表达式声明的类型,如本例是要赋值给SqlDataParameter类型的,它是可以容纳DBNull和object的,不必考虑特殊值的实际可转可赋问题.