中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

在NullObject中C#6.0有哪些改進

發布時間:2021-10-29 18:27:25 來源:億速云 閱讀:119 作者:柒染 欄目:編程語言

今天就跟大家聊聊有關在NullObject中C#6.0有哪些改進,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

什么是空引用異常

作為一個敲過代碼的碼農來說,似乎沒有誰沒有遇到過NullReferenceException這 個問題,有些時候當方法內部調用一個屬性、方法(委托)時,我們控制這些屬性在“外部”的表現(當然某些情況下使用ref關鍵字除外),所以我們要在方法 的內部去判斷屬性、委托方法是否為Null來避免可能的、錯誤使用上帶來的空引用異常,這樣當我們知道如果對象為Null的話,我們會實現符合我們“預 期”的行為。

解決空引用異常---Check Any Where

這很簡單,我只要在需要用的地方檢查一下是否為Null就可以了。是的,這非常簡單,語義也很清晰,但是當你要重復檢查一個對象實體10000萬次時,你的代碼中將存在10000個如下代碼段:

public void Check()         {             if (Person.AlivePerson() != null)             {                 Person.AlivePerson().KeepAlive = true;             }          }

你能容忍這樣的行為嗎?

If(OK)

Continue;

Else

Close;

應用NullObject設計模式

NullObjectPattern出自forth by Gamma(設計模式4人組),核心內容是:提供一個給定對象的空值代理,空值代理中提供不做任何事情的方法實現。

接下來讓我們看看維基百科上的C#實現:

// compile as Console Application, requires C# 3.0 or higher using System; using System.Linq; namespace MyExtensionWithExample {     public static class StringExtensions {          public static int SafeGetLength(this string valueOrNull) {              return (valueOrNull ?? string.Empty).Length;          }     }     public static class Program {         // define some strings         static readonly string[] strings = new [] { "Mr X.", "Katrien Duck", null, "Q" };         // write the total length of all the strings in the array         public static void Main(string[] args) {             var query = from text in strings select text.SafeGetLength(); // no need to do any checks here             Console.WriteLine(query.Sum());         // The output will be: 18          }     } }

在C#語言中,我們通過靜態的擴展方法來實現將檢查方式統一在方法內部,而不是寫的到處都是,上面的例子中是在String類上實現了一個SafeGetLength擴展方法,將為所有String類型提供了一個方法,這樣我們在“代碼整潔”上又進了一步。

下面我們再來看一個更常用的例子---來自于StackOverFlow

public static class EventExtensions     {         public static void Raise<T>(this EventHandler<T> evnt, object sender, T args)             where T : EventArgs         {             if (evnt != null)             {                 evnt(sender, args);             }         }     }

***,說一個細節問題,以上代碼均沒有實現“線程安全”,在大牛Eric Lippert的文章中針對線程安全有過一個更精彩的討論,請戳這里。

改進后的代碼時在方法內部增加了一個臨時變量,作為方法內部的拷貝,實現線程安全,如果有疑問請參考我的《C#堆vs棧》中對方法內部變量在堆棧上的表現一章。

public class SomeClass     {         public event EventHandler<EventArgs> MyEvent;          private void DoSomething()         {             var tmp = MyEvent;              tmp.Raise(this, EventArgs.Empty);         }     }

 

更“潮”的方式-C#6.0語法

    來自MSDN Magazine的Mark Michaelis(《C#本質論》作者)給我們介紹了C#6.0在語言可能帶來的新改進,其中就有針對“Null條件運算符”的改進。

C#6.0更多參考:

Part One: https://msdn.microsoft.com/zh-cn/magazine/dn683793.aspx

Part Two: https://msdn.microsoft.com/zh-cn/magazine/dn802602.aspx

即使是 .NET 開發新手,也可能非常熟悉 NullReferenceException。有一個例外是幾乎總是會指出一個 Bug,因為開發人員在調用 (null) 對象的成員之前未進行充分的 null 檢查。請看看以下示例:

public static string Truncate(string value, int length) {   string result = value;   if (value != null) // Skip empty string check for elucidation   {     result = value.Substring(0, Math.Min(value.Length, length));   }   return result; }

如果不進行 null 檢查,此方法會引發 NullReferenceException。盡管這很簡單,但檢查字符串參數是否為 null 的過程卻稍微有些繁瑣。通常,考慮到比較的頻率,該繁瑣的方法可能沒有必要。C# 6.0 包括一個新的 null 條件運算符,可幫助您更加簡便地編寫這些檢查:

public static string Truncate(string value, int length) {             return value?.Substring(0, Math.Min(value.Length, length)); }  [TestMethod] public void Truncate_WithNull_ReturnsNull() {   Assert.AreEqual<string>(null, Truncate(null, 42)); }

根據 Truncate_WithNull_ReturnsNull 方法所演示的內容,如果對象的值實際上為 null,則 null 條件運算符將返回 null。這帶來了一個問題,即 null 條件運算符在調用鏈中出現時會是什么情況?如以下示例中所示:

public static string AdjustWidth(string value, int length) {   return value?.Substring(0, Math.Min(value.Length, length)).PadRight(length); }  [TestMethod] public void AdjustWidth_GivenInigoMontoya42_ReturnsInigoMontoyaExtended() {   Assert.AreEqual<int>(42, AdjustWidth("Inigo Montoya", 42).Length); }

盡管 Substring 是通過 null 條件運算符進行調用的,并且 null value?.Substring 似乎返回了 null,但語言行為按您的想法進行。這簡化了對 PadRight 的調用過程,并立即返回 null,從而避免會導致出現 NullReferenceException 的編程錯誤。這個概念稱為“null 傳播”。

Null 條件運算符會根據具體條件進行 null 檢查,然后再調用目標方法以及調用鏈中的所有其他方法。這將可能產生一個令人驚訝的結果,例如,text?.Length.GetType 語句中的結果。

如果 null 條件運算符在調用目標為 null 時返回 null,那么調用會返回值類型的成員時最終會是什么數據類型(假定值類型不能為 null)?例如,從 value?.Length 返回的數據類型不能只是 int。答案當然是:可以為 null 的類型(int?)。實際上,嘗試僅將結果分配給 int 將會出現編譯錯誤:

int length = text?.Length; // Compile Error: Cannot implicitly convert type 'int?' to 'int'

Null 條件具有兩種語法形式。首先,問號在點運算符前面 (?.)。其次,將問號和索引運算符結合使用。例如,給定一個集合(而非在索引到集合之前顯式進行 null 檢查),您就可以使用 null 條件運算符執行此操作:

public static IEnumerable<T> GetValueTypeItems<T>(   IList<T> collection, params int[] indexes)   where T : struct {   foreach (int index in indexes)   {     T? item = collection?[index];     if (item != null) yield return (T)item;   } }

此示例使用了運算符 ?[&hellip;] 的 null 條件索引形式,導致僅在集合不為 null 時才索引到集合。通過 null 條件運算符的此形式,T? item = collection?[index] 語句在行為上相當于:

T? item = (collection != null) ? collection[index] : null.

請注意,null 條件運算符僅可檢索項目,不會分配項目。如果給定 null 集合,那么這意味著什么?

請注意針對引用類型使用 ?[&hellip;] 時的隱式歧義。由于引用類型可以為 null,因此對于集合是否為 null,或者是否元素本身實際上就是 null 而言,來自 ?[&hellip;] 運算符的 null 結果不明確。

Null 條件運算符的一個非常有用的應用程序解決了 C# 自 C# 1.0 以來一直存在的的一個特性,即在調用委托之前檢查是否為 null。我們來看一下中顯示的 C# 2.0 代碼。

圖 1 在調用委托之前檢查是否為 Null

class Theremostat {   event EventHandler<float> OnTemperatureChanged;   private int _Temperature;   public int Temperature   {     get     {       return _Temperature;     }     set     {       // If there are any subscribers, then       // notify them of changes in temperature       EventHandler<float> localOnChanged =         OnTemperatureChanged;       if (localOnChanged != null)       {         _Temperature = value;         // Call subscribers         localOnChanged(this, value);       }     }   } }

通過使用 null 條件運算符,整個 set 實現過程就可簡化為:

OnTemperatureChanged?.Invoke(this, value)

現在,您只需對將 null 條件運算符作為前綴的 Invoke 進行調用,不再需要將委托實例分配給本地變量,從而實現線程安全,甚至是在調用委托之前顯式檢查值是否為 null。

C# 開發人員都很想知道在***的四個版本中是否對此內容有所改進。答案是最終進行了改進。僅此一項功能就可以改變調用委托的方式。

另一個 null 條件運算符普及的常見模式是與 coalesce 運算符結合使用。您無需在調用 Length 之前對 linesOfCode 進行 null 檢查,而是可以編寫項目計數算法,如下所示:

List<string> linesOfCode = ParseSourceCodeFile("Program.cs"); return linesOfCode?.Count ?? 0;

在這種情況下,任何空集合(無項目)和 null 集合均標準化為返回相同數量。總之,null 條件運算符將實現以下功能:

1.  如果操作數為 null,則返回 null

2.  如果操作數為 null,則簡化調用鏈中的其他調用

3.  如果目標成員返回一個值類型,則返回可以為 null 的類型 (System.Nullable<T>)。

4.  以線程安全的方式支持委托調用

5.  可用作成員運算符 (?.) 和索引運算符 (?[&hellip;])

看完上述內容,你們對在NullObject中C#6.0有哪些改進有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

通山县| 牟定县| 策勒县| 洪江市| 九龙坡区| 监利县| 柯坪县| 南岸区| 锡林浩特市| 云南省| 克东县| 剑川县| 兰溪市| 平利县| 石楼县| 建始县| 永胜县| 海伦市| 武义县| 来安县| 稻城县| 改则县| 承德县| 手游| 泰来县| 罗源县| 建阳市| 鄄城县| 九江县| 图木舒克市| 长宁区| 扎赉特旗| 全椒县| 拜城县| 洛阳市| 旌德县| 新沂市| 广水市| 清水河县| 花莲县| 霍邱县|