场景一 从数据库取到的可空类型的字段值,在程序代码中该如何保存?
假设数据库存在表tb_Message,该表保存发送给客户的Message记录。
tb_Message表字段的定义说明如下图所示。
其中,除主键id不允许为空外,其他字段均可以为空。
在实际应用中,向用户发送一条Message时,便会向表中的id,title,message,senttime字段写入值,但此时并不会向replytime字段写入值,因为该它的值需在消息被回复时才写入,所以此时该字段会保存null。那么等到消息被回复时,程序代码首先会获取replytime的值再更新,这时便出现了“我们在代码中该怎样保存这样一个可空类型的值?”的问题(这个问题就算在这里不一定会碰见,在其他地方也是会碰见的)。
下面在代码中简单模拟一下发送消息以及消息被回复时修改replytime值的操作。
新建控制台程序,程序主要代码如下所示。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace NullableTExp
{
class Program
{
static void Main(string[] args)
{
Message.SendMessage();
Thread.Sleep(10000);
Message.ReplyMessage();
}
}
public static class Message
{
public static void SendMessage()
{
using (TestDBEntities myDbEntity = new TestDBEntities())
{
tb_Message tbMessage = new tb_Message();
tbMessage.title = "wsp";
tbMessage.message = "你是坏蛋,我要和你决斗,请早点回复我!";
tbMessage.senttime = System.DateTime.Now;
myDbEntity.AddTotb_Message(tbMessage);
int count = myDbEntity.SaveChanges();
Console.WriteLine("消息发送成功!");
}
}
public static void ReplyMessage()
{
using (TestDBEntities myDbEntity = new TestDBEntities())
{
var query = from message in myDbEntity.tb_Message
where message.title == "wsp"
select message;
var m = query.FirstOrDefault();
m.replytime = System.DateTime.Now;
myDbEntity.SaveChanges();
Console.WriteLine("消息有回复啦!");
}
}
}
}
运行程序,一切ok。
下面,我们重点看看ReplyMessage()方法。
ReplyMessage()方法中,查询标题为"wsp"的消息并赋值给匿名变量query,再从匿名变量query取出第一条记录(这里满足条件的也就一条记录)赋值给匿名变量m,并修改m的replytime值为当前系统时间,再将变更保存至数据库。整个过程并没有地方保存可空字段replytime的值,所以就算replytime的值为null也不会出错。
假设,我们在代码中加入下面这行代码:
DateTime t = m.replytime;
编译便会出现错误,提示:
无法将类型“System.DateTime?”隐式转换为“System.DateTime”。存在一个显式转换(是否缺少强制转换?)
出现此错误的原因是:
replytime是可空的时间类型,而t是不可为空的时间类型,将可空的时间类型变量赋值给不可为空的时间类型变量(存在隐式类型转换)是不被编译器允许的。
稍稍修改代码(如下所示),再重新编译代码。
DateTime? t = m.replytime;
此时,一切OK啦。
加上问号,t 就变成了可空的时间类型。
由此可见,使用可空类型接收数据库的可空字段的值可以使操作得到简化。
场景二 向方法传入参数null
现在有下面这样一个方法。
public void DoSomething(int? intParam)
{
if(intParam==null)
{
intParam=xx;//xx为默认设置好的值
}
//下面使用intParam进行操作
}
在使用这个方法时,可以传入参数null代表使用默认的值来运算,传入非null的值代表使用传入的值进行计算。
向方法传入可空类型参数可以减少方法的重载。
场景三 为方法返回null
看下面的方法。
public int? DoSomething(int? intParam)
{
if(intParam>1000)
{
return null;//表示什么也没干
}
else
{
//其他操作
}
}
在这个方法中,返回null代表发方法内部什么都没做,在方法调用处可针对此种情况做一些特殊处理。
就写这些了。对于Nullable<.T>的用途我就知道这些。总之,存在就有存在的道理。在开发中,慢慢去体会吧。
补充阅读:可空类型Nullable<T>小结