public Color? TextColor
{
get { return _textColor; }
set { _textColor = value; }
}
今天看程序代码,发现Color? TextColor 这个属性的申明,感觉很不能理解,后来在google上搜索了一下,原来这是vs2005开始c#新有的特性,具体的说也可以是C#2.0的新特性。
下面是我搜索到得相关描述:
Nullable Types in C#
One of the "late breaking" features in C# 2.0 is what is known as "Nullable Types". The details can be found in the C# 2.0 language spec.
Nullable types address the scenario where you want to be able to have a primitive type with a null (or unknown) value. This is common in database scenarios, but is also useful in other situations.
In the past, there were several ways of doing this:
- A boxed value type. This is not strongly-typed at compile-time, and involves doing a heap allocation for every type.
- A class wrapper for the value type. This is strongly-typed, but still involves a heap allocation, and the you have to write the wrapper.
- A struct wrapper that supports the concept of nullability. This is a good solution, but you have to write it yourself.
To make this easier, in VS 2005, we're introducing a new type named "Nullable", that looks something like this (it's actually more complex than this, but I want to keep the example simple):
struct Nullable<T> { public bool HasValue; public T Value; }
You can use this struct directly, but we've also added some shortcut syntax to make the resulting code much cleaner. The first is the introduction of a new syntax for declaring a nullable type. Rather than typing:
Nullable<int> x = new Nullable<int>(125);
I can write:
int? x = 125;
which is much simpler. Similarly, rather than needed to write a null test as:
if (x.HasValue) {...}
you can use a familiar comparison to null:
if (x != null) {...}
Finally, we have support to make writing expressions easier. If I wanted to add two nullable ints together and preserve null values, if I didn't have language support, I would need to write:
Nullable<int> x = new Nullable<int>(125); Nullable<int> y = new Nullable<int>(33); Nullable<int> z = (x.HasValue && y.HasValue) ?
new Nullable<int>(x.Value + y.Value) : Nullable<int>.NullValue;
At least I think that's what I'd have to write - it's complex enough that I'm not sure this code works. This is ugly enough that it makes using Nullable without compiler support a whole lot of work. With the compiler support, you write:
int? x = 125; int? y = 33; int? z = x + y;
而后又惊异发现居然还有??操作符的存在,感叹原来自己已经落后不止一个时代,也一并贴个用法于下:
The ?? operator returns the left-hand operand if it is not null, or else it returns the right operand.
A nullable type can contain a value, or it can be undefined.
The ?? operator defines the default value to be returned when a nullable type is assigned to a non-nullable type.
If you try to assign a nullable type to a non-nullable type without using the ?? operator,
you will generate a compile-time error.
If you use a cast, and the nullable type is currently undefined, an InvalidOperationException exception will be thrown.
// nullable_type_operator.csusing System; class MainClass { static int? GetNullableInt() { return null; } static string GetStringValue() { return null; } static void Main() { // ?? operator example. int? x = null; // y = x, unless x is null, in which case y = -1. int y = x ?? -1; // Assign i to return value of method, unless // return value is null, in which case assign // default value of int to i. int i = GetNullableInt() ?? default(int); string s = GetStringValue(); // ?? also works with reference types. // Display contents of s, unless s is null, // in which case display "Unspecified". Console.WriteLine(s ?? "Unspecified"); } }下面一片是摘自于dashang 的中文讲解。原文地址(http://blog.chinaitlab.com/user1/370055/archives/2006/45231.html)随着C#语言最新标准的出炉,现在它也提供了对可空类型的支持。这个小变化将会在处理那些包括可选项的数据库记录时非常有用。当然在其他地方,它也是非常有用的。
简单说来,可空数据类型就是包含了所定义的数据类型或者值的空(null)的类型。C#的ECMA-334标准提供了对所有C#值类型的可空版本的描述。
定义可空类型
定义可空类型和非可空类型基本类似,不同的是采用了?来表示。如定义一个整型,你可以使用简单的语句:
int myInt = 1; |
为了使得myInt能够存储一个空值,你可以这样声明它:
int? myNullableInt = 1; |
你可以看到,这两个变量看上去好像是一样的。但是,可空类型的版本是非常不同的。可空的版本事实上是一个结构,它将值类型和一个标记该值是否为空的标志位结合在一起。一个可空类型有两个公共可读的属性,HasValue和value。如果存储了一个值那么HasValue这个布尔型变量就为true。否则,如果变量是空值就是false。如果HasValue是true,你可以获取这个变量的值。如下有两个对可空变量的有效赋值:
double? myDouble = 3.1415926; double? myOtherDouble = null; |
你可以看到,myDouble被赋值了,但是也可以被赋为空。在第二个语句里,myOtherDouble被初始化一个空值,这在一个非可空类型里不能这样做的。
使用可空类型
可空类型可以像普通值类型一样的使用。事实上,可以使用内建的隐式转换来转换相同类型的可空变量和非可空变量。这意味着你可以在一个标准整型和可空整型之间相互转换:
int? nFirst = null; int Second = 2; nFirst = Second; // 有效 nFirst = 123; // 有效 Second = nFirst; // 同样有效 nFirst = null; // 有效 Second = nFirst; // 例外,后者是非空类型 |
在以上的语句里,你可以看到如果可空变量不包含空值的话是可以和非可空变量交换值的。如果它是一个空值,那么就会抛出例外。为了防止例外,你可以使用可空变量的HasValue属性:
if (nFirst.HasValue) Second = nFirst; |
你可以看到,如果nFirst有值赋值就会发生,否则程序会跳过此句语句。
使用可空类型的操作符
虽然可以使用相同值类型的可空和非可空变量的转换,也必须对操作符进行一些改变使得它们可以处理可空和非可空值。这些操作符被称为提升的操作符。
考虑如下代码:
int ValA = 10; int? ValB = 3; int? ValC = ValA * ValB; |
在ValC里存储了什么?ValC中存储了30。标准操作符被扩展使得它们能够处理可空类型。考虑到如下的变化:
int ValA = 10; int? ValB = null; int? ValC = ValA * ValB; |
ValC这次值为多少?ValC为空。无论哪个操作数为空,提升的操作符的结果为空。即使进行加法或减法,结果也为空。
如果ValC不为可空类型呢?如下的代码会有什么样的结果?
int ValA = 10; int? ValB = null; int ValC = ValA * ValB; // ValC 不为可空类型 |
代码将会抛出一个异常。ValA*ValB结果为空,但是不能赋值为非可空类型,这将会导致程序异常的抛出。
比较
比较将会和数学计算操作类似的方式处理。比较的操作数将同时被提升为可空的。这样就可以比较了,如果某个操作数为空,那么比较结果为false。
如果对比是否相等,两个同为空的变量将被认为是相等的。一个空变量和其他任意值的变量相比的结果是不相等。下面是一些比较的例子:
int abc = 123; int xyz = 890; int? def = null; int? uvw = 123; Comparison Result abc == xyz // false abc == def // false def == null // true abc == uvw // true uvw == null // false uvw != null // true |
在所有的比较中,结果都是布尔型值true或者false。在做大小比较的时候,如果操作数的任意一个或者都是空值,那么结果返回的是false。如下展示了一些例子:
Comparison Result abc > uvw // false, they are equal abc < def // false, def is null uvw < def // false, because def is null def > null // false, because right side is null uvw > null // false, because right side is null |
可空性的移去
C#在新版本中加入了一个新的操作符,它被称为空接合操作符,使用如下的格式:
returnValue = first second; |
这样,如果first不为空,那么它的值将返回作为returnValue的值。如果first为空,那么second的值将被返回。注意:returnValue可以为可空变量或者非可空变量。
如果你希望可空变量的值到一个非可空的版本,你可以这样做:
int? ValA= 123; int? ValB = null; int NewVarA = ValA ?? -1; int NewVarB = ValB ?? -1; |
NewVarA的值将会为123因为ValA不是空值。NewVarb的值是-1因为ValB是空值。你看一看到,这里你将可以将变量从一个空值转化成一个缺省值。这里缺省值是-1。
结束语
总得来说,最新的C#允许一个可空类型的存在。语言内部建立了对可空类型的处理机制。可空类型使得数据库记录和其他可选信息更加的容易处理