使用int?來確保值類型也可以為null

2021-03-02 小市民在西河

繼上一篇「你確認C#中TryParse比Parse好?動手測試才知道!」後,本文繼續講《編寫高質量代碼改善C#程序的157個建議》一書第5個建議「使用int?來確保值類型也可以為null」。喜歡本書請到各大商城購買原書,支持正版。

基元類型為什麼需要為null?考慮兩個場景:

資料庫中一個int欄位可以被設置為null。在C#中,值被取出來後,為了將它賦值給int類型,不得不首先判斷一下它是否為null。如果將null直接賦值給int 類型,會引發異常。

在一個分布式系統中,伺服器需要接收並解析來自於客戶端的數據。一個int型數據可能在傳輸過程中丟失或被篡改了,轉型失敗後應該保存為null值,而不是提供一個初始值。

類似的場景還有很多,所以從.NET 2.0開始,FCL中提供了一個額外的類型:可以為空的類型Nullable。它是一個結構體,聲明如下:

[SerializableAttribute]
public struct Nullable<T> where T : struct

因為是結構體,所以只有值引用類型才可以作為「可以為空的類型」(引用類型本身就可以為null)。一個可以為空的int類型表示為:

Nullableeint> i = null;

它也可以表示為:

int? i = null;

語法T?是 Nullable的簡寫,兩者可以相互轉換。可以為 null 的類型表示其基礎值類型正常範圍內的值再加上一個null值。例如,Nullable,其值的範圍為—2147 483 648~2 147 483 647,再加上一個null值。

現在來看看可空類型和基元類型的互相轉換。基元類型提供了其對應的可空類型的隱式轉換,如下所示:

int? i = null;
int j = 0;
i = j;

反過來,可空類型不可隱式轉換為對應的基元類型,正確的轉換形式如下:

int? i = 123;
int j;
if (i.Hasvalue)
{
  j = i.value;
}
else
{
  j = 0;
)

但是,這段代碼看上去是不是有點煩瑣?所以,在闡述可空類型的時候,不得不提到??運算符。??最大的用處就是將可空類型的值賦值給對應的基元類型進行簡化,上文代碼的一個簡化形式就是:

int? i = 123;
int j = i ?? 0;

int j = i ?? 0;表示的意思是,如果i的HasValue為 true,則將i的value賦值給j:否則,就給j賦值為0。

下一篇我們接著讀《建議6:區別readonly和const的使用方法》,歡迎關注微信公眾號【小市民在西河】。

相關焦點

  • 為什麼建議你用nullptr而不是NULL?
    因為C++中不能將void *類型的指針隱式轉換成其他指針類型,從下面的例子可以看出來:#include<iostream>int main(void){    char p[] = "12345";    int *a = (void*)p;    return 0;}
  • 深入理解Java關鍵字null
    因此可以將null賦給引用類型變量,但不可以將null賦給基本類型變量。比如:int a = null是錯誤的,而Ojbect o = null是正確的。Java中變量的使用都遵循一個原則:先定義並且初始化後才可以使用。我們不能在定義int a後,不給a指定值,就去列印a的值,這對於引用類型變量也是適用的。
  • Java中當對象不再使用時,不賦值為null會導致什麼後果 ?
    鑑於網上有太多關於此問題的誤導,本文將通過實例,深入JVM剖析「對象不再使用時賦值為null」這一操作存在的意義,供君參考。本文儘量不使用專業術語,但仍需要你對JVM有一些概念。對比兩段代碼,僅僅將placeHolder賦值為null就解決了GC的問題,真應該感謝「不使用的對象應手動賦值為null「。等等,為什麼例子裡placeHolder不賦值為null,GC就「發現不了」placeHolder該回收呢?這才是問題的關鍵所在。
  • NullPointerException空指針異常的處理技巧
    null對象自動拆箱(本質也是上面兩種)這裡來解釋一下Java的自動裝箱和拆箱,簡單地說,裝箱就是自動將基本數據類型轉換成包裝器類型,拆箱就是自動將包裝器類型轉換成基本數據類型。上邊例子中的「int i = integer」,自動拆箱,實際上就是自動調用integer的intValue,null對象調用方法,出現NullPointerException(空指針異常),反過來「Integer integer = i」,自動裝箱,就是調用Integer的valueOf(int)方法。
  • 關於nullptr這篇文章你一定要看
    主要規定空指針常量需要被轉化成指針類型,同時這個轉化為指針類型的值還不能和其它的對象指針或者函數指針的值相同。兩個空指針常量的值還需要相等。這裡可以總結三點:使用nullptr可以不用擔心整型和指針類型的重載,不會產生二義性導致編譯失敗。0和空指針分別表示不同的含義,使用nullptr可以更好的支持模板編程。使用nullptr使代碼更安全,讓用戶編寫代碼更清晰直觀。
  • 變量類型測試函數的使用:二、is_int的用法
    昨天剛講完PHP變量類型測試函數【is_bool】的用法,今天來講講PHP變量類型測試函數【is_int】的用法。is_intis_int (字面意思) — 檢測變量的類型是否為整數is_int描述is_int ( mixed $var ) : bool「is_int 函數參數可以混合類型「混合類型:一個參數可以接受多種不同的類型
  • MSSQL數據類型-整數數據類型(bigint、int、smallint、tinyint)
    bigint型數據可以存儲的數值範圍是-263~263-1,即 -9 223 372 036 854 775 808 ~9 223 372 036 854 775 807。 在應用中除非明確說明,否則那些接受int表達式作為其參數的函數、語句和系統存儲過程都不會改變,從而不會支持將 bigint表達式隱式轉換為這些參數。
  • 變量類型測試函數的使用:八、剩餘函數的使用方法
    講完PHP變量類型測試函數【is_resource】的用法,今天來講講PHP變量類型測試函數【is_null、is_scalar、is_numeric、is_callable】的用法。is_nullis_null — 檢測變量是否為 NULLis_null 描述is_null ( mixed $var ) : bool如果 var 是 null 則返回 TRUE,否則返回 FALSE
  • 詳解PHP 7.4 的類型屬性
    Foo::$barmust not be accessed before initialization從錯誤消息中可以看出,出現了一種新的變量狀態:未初始化 (uninitialized)$bar 屬性無論是否聲明了類型,值都可以為 null。
  • Java新特性:數據類型可以扔掉了?
    然而到了 JDK 10 時,我們就有了新的選擇,JDK 10 中新增了 var 局部變量推斷的功能,使用它我們可以很 happy 的忘記數據類型這件事了,那它是如何使用的呢?接下來我們一起來看。使用對比接下來我們就使用對比的方式,來體會一下 var 的作用。
  • 為什麼 MySQL 不推薦默認值為 null ?
    NULL值是一種對列的特殊約束,我們創建一個新列時,如果沒有明確的使用關鍵字not null聲明該數據列,MySQL會默認的為我們添加上NULL約束。有些開發人員在創建數據表時,由於懶惰直接使用Mysql的默認推薦設置.
  • 不懂就問:為什麼MySQL不建議使用NULL作為列默認值?
    NULL值是一種對列的特殊約束,我們創建一個新列時,如果沒有明確的使用關鍵字not null聲明該數據列,Mysql會默認的為我們添加上NULL約束.有些開發人員在創建數據表時,由於懶惰直接使用Mysql的默認推薦設置.(即允許欄位使用NULL值).而這一陋習很容易在使用NULL的場景中得出不確定的查詢結果以及引起資料庫性能的下降.
  • 變量類型測試函數的使用:七、is_resource的用法
    is_resourceis_resource — 檢測變量是否為資源類型is_resource 描述is_resource ( mixed $var ) : bool「is_resource函數參數和前六個變量測試函數的用法是一模一樣的可以混合類型
  • Python 基本數據類型簡介int/str/bool
    一、python基本數據類型1. int ==> 整數.主要用來進行數學運算2. str ==> 字符串, 可以保存少量數據並進行相應的操作3. bool==>判斷真假, True, False4. list==> 存儲大量數據.用[ ]表示5. tuple=> 元組, 不可以發生改變 用( )表示6. dict==> 字典, 保存鍵值對, 一樣可以保存大量數據
  • 那些可以提升pandas的使用小技巧、你知道了嗎
    興趣 object畢業否 bool存款 int64dtype: object2.1.通過select_dtypes方法選擇數值列、也就是數據類型為 int64、 float64的列df.select_dtypes(include='number')
  • SQL Server null知多少?
    與true和false相比,null最難以令人捉摸,因為它沒有明確的值,在不同的場景下,它能代表不同的含義。下文以例子的方式給大家分享下null使用的典型場景及對應的用法。1.check約束與null之前在SQL ServerCentral.com上看到一個關於check約束的null問題,作者創建了一個表,在欄位orderstatus上設置了check約束,只能插入指定的value的行,現在插入幾行數據,其中有一行的value為null,最後問最終有幾行可以插入成功。
  • null == undefined ?
    與 null 相關的另外一個問題需要解釋一下:typeof null == 'object'  null 有屬於自己的類型 Null,而不屬於Object類型,typeof 之所以會判定為 Object 類型,是因為JavaScript 數據類型在底層都是以二進位的形式表示的,二進位的前三位為 0 會被 typeof 判斷為對象類型,而 null 的二進位位恰好都是
  • Java String轉int還有這種寫法
    那這次來分享一個新的知識點,我敢賭一包衛龍辣條(打錢來),很多同學不一定知道。在 Java 中,String(字符串) 和 int(整形) 是兩種不同的數據類型,字符串可以把許多字符串起來,整形嘛——就是整形了。(同學們可能會疑惑,這個知識點我能不知道,別蒙我好不好?繼續往下看唄。吃大餐之前,還能不來點小吃或者涼菜?)
  • java 這些地方容易遭遇 NullPointerException異常
    磨刀不誤砍柴工,不太清楚空指針的朋友可以先讀一下上面那篇文章,會有所啟發。我們進入今日的主題,哪些代碼會碰到:NullpointerExcetion? 先看一段代碼。getHtmlLenght(String pageSource) { return pageSource.length();}這段代碼沒有對傳入的pageSource做null檢查,一旦pageSource的值為為空,空指針錯誤就來了。
  • 釐清C++類型轉換
    筆者之前寫的Python與Go都是強類型的語言,對這種弱類型的設計實在是接受無力啊 ( 生活所迫,工作還得寫C++啊)C++語言提供了四種類型轉換的操作:static_cast,dynamic_cast,reinterpret_cast,const_cast,今天就來聊一聊,在C++之中應該如何來使用這些類型轉換的。