C# 7 新特性-2


在之前的C# 7 新特性博客中,我們談到了Tuples,Record Type和Pattern Matching。這些都是C#新特性中最可能出現的。在本博客中,我們會提到更多的一些特性,雖然這些特性不像之前的有那么多的關注,但也是很有用的特性。

來源https://www.kenneth-truyers.net/2016/01/25/new-features-in-c-sharp-7-part-2/?utm_campaign=C%23%2BWeekly&utm_medium=email&utm_source=C%23_Weekly_44

Non-nullable引用類型##

What###

c#2.0中引入了可空值類型,本質上它是Nullable 類的語法糖。而Non-nullable是這種特性的逆特性。它可以允許你聲明一個保證不可為null的引用類型。

Why###

空引用一直被稱之為"The billion dollar mistake"(Tony Hoare)。NullReference異常太常見了。問題是有兩方面的,要么你沒有檢測null值,造成運行時異常;要么你檢查了他們,你的的代碼變成了垃圾堆,充斥着檢測null的代碼,而卻缺少真正需要的語句。聲明一個不可為null的引用類型可以克服這個問題。

How###

注意:下面的語法是尚未確定下來的,仍可能變動。目前有各種各樣的提議,所以不清楚具體的形式會是什么樣子。當我提到"error"時,尚不清楚是兼容性錯誤還是只是warning。
首先,最理想的做法是,引用類型默認為Non-nullable的,這樣可以和值類型的默認也是Non-nullable相對應,如下。

int a;     //non-nullable value type
int? b;    //nullable value type
string c;  //non-nullable reference type
string? d; //nullable reference type

然而,這種做法兼容性非常不好。之前存在的數百萬千萬行代碼,會因為引用類型默認為Non-nullable而break。所以必須使用不同的方式,以滿足向前兼容。目前提議的做法如下。

int a;     //non-nullable value type
int? b;    //nullable value type
string! c; //non-nullable reference type
string d;  //nullable reference type

使用nullbale類型和Non-nullable類型會影響編譯器。

MyClass a;  // Nullable reference type
MyClass! b; // Non-nullable reference type
 
a = null;   // OK, this is nullable
b = null;   // Error, b is non-nullable
b = a;      // Error, n might be null, s can't be null
 
WriteLine(b.ToString()); // OK, can't be null
WriteLine(a.ToString()); // Warning! Could be null!
 
if (a != null) { WriteLine(a.ToString); } // OK, you checked
WriteLine(a!.Length); // Ok, if you say so

這種語法兼容性是沒問題的,但是對於泛型卻會有問題。

/ The Dictionary is non-nullable but string, List and MyClass aren't
Dictionary<string, List<MyClass>>! myDict;   
 
// Proper way to declare all types as non-nullable
Dictionary<string!, List<MyClass!>!>! myDict;

如上,卻不便於閱讀。一種簡便的形式如下。

// Typing ! in front of the type arguments makes all types non-nullable
Dictionary!<string, List<MyClass>> myDict;

局域函數local functions##

What###

允許你在區域作用域內聲明方法和類型。

Why###

通過Func和Action匿名方法在一定程度上可以這么做。但是這樣缺少一些特性,如下

  • 泛型
  • **ref和out參數
  • params

How###

public int Calculate(int someInput)
{
    int Factorial(int i)
    {
        if (i <= 1)
            return 1;
        return i * Factorial(i - 1);
    }
    var input = someInput + ... // Other calcs
 
    return Factorial(input);
}

不可變類型##

What###

不可變對象是在對象創建之后,其狀態不能被修改。

Why###

不可變對象有如下好處:

  • 天生的線程安全
  • 更容易使用和推測代碼
  • 更方便並行編程
  • 不可變類型可以緩存,因為他們不會改變

目前,也是有可能去聲明不可變對象的,如下

public class Point
{
    public Point(int x, int y)
    {
        x = x;
        Y = y;
    }
 
    public int X { get; }
    public int Y { get; }
}

如上雖然聲明定義了不可變對象,但是其意圖卻是不明顯的。也許某一天有人對其添加了setter,那對其他的使用者來說,就會有不一樣的結果。

How###

注意:再一次說明,如下語法是尚未固定的。初始的提案是添加immutable關鍵字。

public immutable class Point
{
    public Point(int x, int y)
    {
        x = x;
        Y = y;
    }
 
    public int X { get; }
    public int Y { get; }
}

當有了不可變類型之后,在語言上就可以支持基於不同的一個實例來創建一個新的實例,如下。

var a = new Point(2, 5);
var b = a with { X = 1};

總結##

如上所述,仍是C# 7的早期階段,如上語法很有可能會變。但是這些特性非常令人exciting的,也會使C#編程變得更愉悅。鼓勵大家去Github上去看有關特性的目前的討論情形。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM