zoukankan      html  css  js  c++  java
  • 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上去看有关特性的目前的讨论情形。

  • 相关阅读:
    模拟实现链表
    模拟实现内存操作函数
    实现一个简单的进度条
    简单的通讯录(C语言实现)
    sizeof和strlen
    动态联编
    不用第三个变量交换两个变量的值
    内存对齐
    字符串指针和字符数组的区别
    vs中的一些bug解决
  • 原文地址:https://www.cnblogs.com/yanbinliu/p/5208431.html
Copyright © 2011-2022 走看看