原文链接:http://msdn.microsoft.com/zh-tw/library/2cf62fcy%28VS.80%29.aspx

使用可為 Null 的型別 (C# 程式設計手冊)

Visual Studio 2005
其他版本
本主題尚未接受評分 - 為這個主題評分

可為 Null 的型別可以代表基礎型別的所有值,也可以代表另一個 null 值。您可以使用下列其中一種方法宣告可為 Null 的型別:

System.Nullable<T> variable

-或-

T? variable

T 是可為 Null 之型別的基礎型別,T 可以是任何實值型別 (包括 struct,但不能是參考型別)。

何 時該使用可為 null 的型別,可舉一般的布林變數為例,這種變數有兩個可能的值:true 和 false。但沒有值可以代表「未定義」。在許多設計程式的應用程式中,特別是資料庫互動的程式,變數有可能是以未定義的狀態存在。例如,資料庫中的某個 欄位可能包含 true 或 false 值,但也可能不包含任何值。同樣地,參考型別可以設定為 null 表示其並非初始化的。

由於這些值的性質不同,就需要在程式上另做設計,包括使用其他變數存放狀態資訊、使用特殊值等等。可為 null 的型別修飾詞能夠讓 C# 建立表示未定義之值的實值型別 (Value Type) 變數。

任何實值型別都可以當做可為 null 的型別的基礎,例如:

 
int? i = 10;
double? d1 = 3.14;
bool? flag = null;
char? letter = 'a';
int?[] arr = new int?[10];

可為 null 之型別的每個執行個體 (Instance) 有兩個公用唯讀屬性:

  • HasValue

    HasValue 屬於 bool 型別。當變數包含非 null 的值時,該屬性會設定為 true

  • Value

    Value 的型別與基礎型別相同。如果 HasValuetrueValue 會包含有意義的值。如果 HasValuefalse,存取 Value 將會擲回 InvalidOperationException

在這個範例中,會先使用 HasValue 成員測試變數是否包含值,然後才嘗試顯示該值。

 
int? x = 10;
if (x.HasValue)
{
System.Console.WriteLine(x.Value);
}
else
{
System.Console.WriteLine("Undefined");
}

您也可以使用下列方式測試值:

 
int? y = 10;
if (y != null)
{
System.Console.WriteLine(y.Value);
}
else
{
System.Console.WriteLine("Undefined");
}

您可以明確使用轉型或使用 Value 屬性,將可為 null 的型別轉換成標準型別。例如:

 
int? n = null;

//int m1 = n;      // Will not compile.
int m2 = (int)n; // Compiles, but will create an exception if x is null.
int m3 = n.Value; // Compiles, but will create an exception if x is null.

如果在兩資料型別之間定義了使用者定義轉換,這兩個資料型別的可為 Null 的型別版本也可以使用該轉換。

可為 Null 的型別也可以使用預先定義的一元和二元運算子,以及現有實值型別的任何使用者定義運算子。如果運算元都是 null,這些運算子就會產生 null 值,否則運算子會使用所包含的值計算結果。例如:

 
int? a = 10;
int? b = null; a++; // Increment by 1, now a is 11.
a = a * 10; // Multiply by 10, now a is 110.
a = a + b; // Add b, now a is null.

使用可為 Null 的型別執行比較時,如果其中一個可為 Null 的型別是 null,比較的評估結果一定會是 false。因此,請千萬不要認為比較結果為 false 時,反之就是 true。例如:

 
int? num1 = 10;
int? num2 = null;
if (num1 >= num2)
{
System.Console.WriteLine("num1 is greater than or equal to num1");
}
else
{
// num1 is NOT less than num2
}

因為 num2null 導致其中並未包含值,所以上述 else 陳述式中的結果無效。

兩個皆為 null 之可為 Null 的型別,其比較的評估結果將會是 true

?? 運算子會定義當可為 null 的型別指派給不可為 null 的型別時,要傳回的預設值。

 
int? c = null;

// d = c, unless c is null, in which case d = -1.
int d = c ?? -1;

這個運算子也可以搭配多個可為 null 的型別使用。例如:

 
int? e = null;
int? f = null; // g = e or f, unless e and f are both null, in which case g = -1.
int g = e ?? f ?? -1;

可為 null 的 bool? 型別可包含三種不同的值:truefalsenull。因此無法在條件中使用,例如使用 ifforwhile。例如,這個程式碼會出現 編譯器錯誤 CS0266 的編譯失敗:

 
 
bool? b = null;
if (b) // Error CS0266.
{
}

因為在條件內容中 null 表示的意義不明確,所以不允許這項動作。可為 Null 的布林值可以明確轉換成 bool 以便在條件中使用,但是如果物件包含 null 值,就會擲回 InvalidOperationException。因此在轉換為 bool 之前先檢查 HasValue 屬性是很重要的。

可為 Null 的布林值類似於 SQL 使用的布林變數型別。為確保 &| 運算子產生的結果與 SQL 的三值布林型別一致,程式提供下列預先定義的運算子:

bool? operator &(bool? x, bool? y)

bool? operator |(bool? x, bool? y)

這些運算子的結果列於下表:

X y x&y x|y

True

true

True

true

True

false

False

true

True

null

Null

true

False

true

False

true

False

false

False

false

False

null

False

null

Null

true

Null

true

Null

false

False

null

Null

null

Null

null

參考

Box 處理可為 Null 的型別 (C# 程式設計手冊)

概念

C# 程式設計手冊
可為 Null 的型別 (C# 程式設計手冊)

[转]C#中的?和??的更多相关文章

  1. Python开源框架

    info:更多Django信息url:https://www.oschina.net/p/djangodetail: Django 是 Python 编程语言驱动的一个开源模型-视图-控制器(MVC) ...

  2. mapreduce中一个map多个输入路径

    package duogemap; import java.io.IOException; import java.util.ArrayList; import java.util.List; imp ...

  3. Hadoop 中利用 mapreduce 读写 mysql 数据

    Hadoop 中利用 mapreduce 读写 mysql 数据   有时候我们在项目中会遇到输入结果集很大,但是输出结果很小,比如一些 pv.uv 数据,然后为了实时查询的需求,或者一些 OLAP ...

  4. Python中的多进程与多线程(一)

    一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...

  5. .NET Core中的认证管理解析

    .NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...

  6. Angular杂谈系列1-如何在Angular2中使用jQuery及其插件

    jQuery,让我们对dom的操作更加便捷.由于其易用性和可扩展性,jQuer也迅速风靡全球,各种插件也是目不暇接. 我相信很多人并不能直接远离jQuery去做前端,因为它太好用了,我们以前做的东西大 ...

  7. 关于CryptoJS中md5加密以及aes加密的随笔

    最近项目中用到了各种加密,其中就包括从没有接触过得aes加密,因此从网上各种查,官方的一种说法: 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学 ...

  8. In-Memory:在内存中创建临时表和表变量

    在Disk-Base数据库中,由于临时表和表变量的数据存储在tempdb中,如果系统频繁地创建和更新临时表和表变量,大量的IO操作集中在tempdb中,tempdb很可能成为系统性能的瓶颈.在SQL ...

  9. SQL Server中的高可用性(2)----文件与文件组

        在谈到SQL Server的高可用性之前,我们首先要谈一谈单实例的高可用性.在单实例的高可用性中,不可忽略的就是文件和文件组的高可用性.SQL Server允许在某些文件损坏或离线的情况下,允 ...

  10. 【.net 深呼吸】序列化中的“引用保留”

    假设 K 类中有两个属性/字段的类型相同,并且它们引用的是同一个对象实例,在序列化的默认处理中,会为每个引用单独生成数据. 看看下面两个类. [DataContract] public class 帅 ...

随机推荐

  1. Sqli-labs less 22

    Less-22 本关和less20.less21是一致的,我们可以从源代码中看到这里对uname进行了"uname"的处理,可以构造payload: admin1"and ...

  2. POJ 2464 Brownie Points II (树状数组,难题)

    题意:在平面直角坐标系中给你N个点,stan和ollie玩一个游戏,首先stan在竖直方向上画一条直线,该直线必须要过其中的某个点,然后ollie在水平方向上画一条直线,该直线的要求是要经过一个sta ...

  3. ***Xcode Interface Builder或Storyboard中可建立那两种连接?

    在Xcode Interface Builder或Storyboard中,可建立到输出口(IBOutlet)和操作(方法,IBAction)的连接. IBOutlet are for output C ...

  4. WCF传输Dataset大数据量 -压缩

    由于WCF不能传输DataTable(不能序列化),所以更多项目中都会使用DataSet作为查询集合的首选返回类型,但是由于DataSet会生成很多的状态信息等,所以DataSet体积也会变大,有几种 ...

  5. UVA 557 Burger 排列组合递推

    When Mr. and Mrs. Clinton's twin sons Ben and Bill had their tenth birthday, the party was held at t ...

  6. android自动化环境搭建

    android自动化环境安装指南 1.appium相关安装(eclipse下)见http://www.cnblogs.com/wangcp-2014/p/5717589.html参考selenium的 ...

  7. Spring REST for DELETE Request Method Not Supoorted

    http://stackoverflow.com/questions/22055251/sending-data-with-angularjs-http-delete-request I have a ...

  8. MySQL数据库的基本操作命令

    MySQL数据库的基本操作命令 [mysql]mysql 常用建表语句 一.mysql服务操作 net start mysql //启动mysql服务 net stop mysql //停止mysql ...

  9. iOS 开发--NSMutableArray使用枚举方法

    可变数组也可以使用枚举方法, 我们在这里提供了两种枚举方法, 一个是正序枚举, 一个是倒序枚举, 在正序枚举中, 元素的个数和顺序都是不可以修改的, 但是在倒序枚举中却可以修改, 这有些耐人寻味. 涉 ...

  10. wordpress模块无法拖拽/显示选项点击无反应

    问题:wordpress模块无法拖拽/显示选项点击无反应,还有编辑器的全屏什么的都用不了,按F12查看了console,提示很多jQuery is not defined... 解决方法:把wp-in ...