• c#6.0/7.x新特性(一)


    记录一些对写代码会有帮助,但是平时像不太到的新特性

    c#6.0

    自动属性初始化

    在类初始化时,会使用后面的表达式初始化该属性

    public ICollection<double> Grades { get; } = new List<double>();
    

    表达式作为成员主体

    这个和上一个可能有点像,但是作用完全不同,这个属性/函数的值,会在每次调用时重新计算,而不是初始化时

    public override string ToString() => $"{LastName}, {FirstName}";
    //或者
    public string FullName => $"{FirstName} {LastName}";
    

    static引用

    通过在using后增加static,可以直接引用命名空间中的静态方法,而不用在前面带上类名

    using static System.Math;
    

    此后,可以直接引用Sin/Sqrt等方法,而不用写上Math.Sin

    空条件操作符?.

    原来如下操作

    var handler = this.SomethingHappened;
    if (handler != null)
        handler(this, eventArgs);
    

    可以被简化为:

    // preferred in C# 6:
    this.SomethingHappened?.Invoke(this, eventArgs);
    

    字符串拼接

    这个是非常方便的特性,从传统的基于位置的字符串格式化

    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", FirstName, LastName);
        }
    }
    

    通过在字符串前增加$符号,可以直接在字符串中带入变量:

    public string FullName => $"{FirstName} {LastName}";
    

    异常过滤

    try/catch语句除了根据异常类型,还能通过when操作符过滤额外条件:

    public static async Task<string> MakeRequest()
    {
        WebRequestHandler webRequestHandler = new WebRequestHandler();
        webRequestHandler.AllowAutoRedirect = false;
        using (HttpClient client = new HttpClient(webRequestHandler))
        {
            var stringTask = client.GetStringAsync("https://docs.microsoft.com/en-us/dotnet/about/");
            try
            {
                var responseText = await stringTask;
                return responseText;
            }
            catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
            {
                return "Site Moved";
            }
        }
    }
    

    nameof表达式

    nameof返回变量名称的字符串表达

    if (IsNullOrWhiteSpace(lastName))
        throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));
    

    当然可以直接在字符串中写入固定的值,不过通过nameof,当通过vs重构变量名时,这里的代码编辑器会帮助自动修改,这是nameof的好处

    await允许被用在catch/finally代码块中

    这在之前的c#是不允许的。不过要小心,不要引入新的异常,要不原有异常就看不到了。。。

    通过索引初始化

    之前数组型的集合可以被容易的初始化,而字典等非线性则不如数组初始化那么轻松,不过现在c#也支持了更为友好的初始化语法:

    private Dictionary<int, string> webErrors = new Dictionary<int, string>
    {
        [404] = "Page not Found",
        [302] = "Page moved, but left a forwarding address.",
        [500] = "The web server can't come out to play today."
    };
    

    为数组初始化扩展Add方法

    Collection如果想使用集合初始化方式初始化一个类,那么类必须实现Add方法

    public class Enrollment : IEnumerable<Student>
    {
        private List<Student> allStudents = new List<Student>();
    
        public void Enroll(Student s)
        {
            allStudents.Add(s);
        }
    
        public IEnumerator<Student> GetEnumerator()
        {
            return ((IEnumerable<Student>)allStudents).GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable<Student>)allStudents).GetEnumerator();
        }
    }
    
    //这在之前版本是不行的,因为Enrollment类只有Enroll,没有Add方法
    var classList = new Enrollment()
    {
        new Student("Lessie", "Crosby"),
        new Student("Vicki", "Petty"),
        new Student("Ofelia", "Hobbs")
    };
    

    而现在,通过将Enroll对应到Add方法,就可以了。

    public static class StudentExtensions
    {
        public static void Add(this Enrollment e, Student s) => e.Enroll(s);
    }
    

    更好的重载判断

    static Task DoThings() 
    {
         return Task.FromResult(0); 
    }
    Task.Run(DoThings); 
    

    在之前版本,编译器无法识别调用的是Task.Run(Action)还是Task.Run(Func<Task>()),会报错
    新版的编译器能够正确将其识别为Task.Run(Func<Task>())了。

    确定编译输出

    c#编译出来的二进制文件,即使源代码没有改,也会因为添加时间戳、GUID等每次独立生成的信息而有所不同
    通过增加-deterministic选项,能让编译器每次生成完全一致的二进制输出

  • 相关阅读:
    一天摄入多少蛋白质比较合理?
    给函数添加元数据(python)
    反转链表(C++实现)
    删除链表的中间节点(C++实现)
    在双向链表中删除倒数第K个链表节点(C++实现)
    在单链表中删除倒数第K个节点(C++实现)
    二叉树的创建及遍历(递归和非递归C++实现)
    删除排序数组中的重复项(C++实现)
    打印两个有序链表的公共部分(C++实现)
    用一个栈实现另一个栈的排序(C++实现)
  • 原文地址:https://www.cnblogs.com/mosakashaka/p/12608195.html
Copyright © 2020-2023  润新知