最近研究了一下C#2.0中的可空类型发现一些有趣的事实,请看代码
int? a = null;
object b = a;
则下面的逻辑表达式结果如何?
a==null //true
b==null //false
奇怪吗?
第一个逻辑表达式为true是意料之中的,而第二个表达式为false就有些意料之外了,但仔细想一下,就会感觉有它存在的道理。我们都知道int?就是Nullable<int>的缩写,而在.Net Framework中Nullable<T>实现其实是一个继承自值类型的结构,只是这个结构多了个属性HasValue,用来标识结构中是否有值,这样再理解上面的结果就不奇怪了,因为语句object b = a;会有一个装箱操作,也就是b中的引址为指向装箱后的a结构,而不是空引用,因此就会有上面的结果了。
这点只是C#语言中的一些小细节,但在很多时候可能会引起些不可以预料的事果,比如微软发布的DataAccessBlock中用来把存储过程的参数数组的时候SqlHelper中的代码
        private static void AttachParameters(SqlCommand command, SqlParameter[] commandParameters)
        
{
            
if (command == nullthrow new ArgumentNullException("command");
            
if (commandParameters != null)
            
{
                
foreach (SqlParameter p in commandParameters)
                
{
                    
if (p != null)
                    
{
                        
if ((p.Direction == ParameterDirection.InputOutput ||
                            p.Direction 
== ParameterDirection.Input) &&
                            (p.Value 
== null))
                        
{
                            p.Value 
= DBNull.Value;
                        }

                        command.Parameters.Add(p);
                    }

                }

            }

        }
在某些情况下将不在有效,因为p.Value为空的判断p.Value==null在p.Value中存贮可空类型的时候可能会失效(如果p.Value中存贮的对象是可空类型,而它的值刚好为空时p.Value == null会返回false但在这种情况下我们仍应该将p.Value赋值为DBNull.Value),这时会导致运行对象没有实现IConvertable的出错信息。 改后代码如下:
        private static void AttachParameters(SqlCommand command, SqlParameter[] commandParameters)
        
{
            
if (command == nullthrow new ArgumentNullException("command");
            
if (commandParameters != null)
            
{
                
foreach (SqlParameter p in commandParameters)
                
{
                    
if (p != null)
                    
{
                        
if (p.Direction == ParameterDirection.InputOutput ||
                            p.Direction 
== ParameterDirection.Input)
                        
{
                            
if (p.Value != null)
                            
{
                                Type typeInf 
= p.Value.GetType();
                                
if (typeInf.Name == "Nullable`1" &&
                                    (
bool)typeInf.GetProperty("HasValue").GetValue(p.Value, null== false)
                                
{
                                    p.Value 
= DBNull.Value;
                                }

                            }

                            
else
                            
{
                                p.Value 
= DBNull.Value;
                            }

                        }

                        command.Parameters.Add(p);
                    }

                }

            }

        }


总的来讲可空类型为我们提供了很大的方便,特别是在对数据库的可空字段的操作提供了方便,但使用时应注意上面的情况才能作到万无一失。