C#6.0 新新特性

C#技术经理对C#6.0新特性的解读,可能需要翻墙

总的来说,很少全新的概念,主要的目的是在C#6.0中添加一些小而实用的新功能,以便清理你的代码

1. 自动属性初始化(Auto-property initializers)

在以前版本的C#代码中所有的自动属性都必须有Setter,这对不变的属性来说很不方便,现在允许只有getter。注意,不能只有Setter:

只有 setter

   public class Point
    {
        public int X { get; }

        public int Y { get; }

        public double Dist
        {
            get { return Math.Sqrt(X * X + Y * Y); }
        }

        public override string ToString()
        {
            return String.Format("({0}, {1})", X, Y);
        }
    }

同时现在也可以为自动属性直接设置初值,无需放到构造函数中

    public class Account
    {
        public string Name { get; set; } = "summit";

        public int Age { get; set; } = 22;

        public IList<int> AgeList
        {
            get;
            set;
        } = new List<int> { 10, 20, 30, 40, 50 };

    }

对于只读属性也可以这样直接初始化(C#5.0不支持),也可以直接在构造函数里初始化

 public class Customer
    {
        public string Name { get; }
        public Customer(string first, string last)
        {
            Name = first + " " + last;
        }
    }

2. 字符串内插(String interpolation)

在之前版本的String.Format中有多少个参数就要写多少个占位符还必须按照顺序,否则就报错。很庞大,参数一多,这样搞的话确实头疼。$ 表示这是一个内插的字符串,留出空位,把要设置格式的字符串放在相应的空位中。看个例子

 public class Account
    {
        public string Name { get; set; } = "summit";

        public int Age { get; set; } = 22;
    }

Console.WriteLine($"Age:{account.Age}  Name:{account.Name}");
Console.WriteLine($"Age:{account.Age}");
Console.WriteLine($"{(account.Age <= 22 ? "Youth" : "Oldman")}");

3. 导入静态类(Using Static)(枚举也是)

像之前使用Math这个静态类的时候要先导入System命名空间后才能使用它.现在可以直接导入这个静态,然后代码中直接使用其函数

using static System.Math;

//这就是使用后的区别
Math.Pow(4, 2);
Pow(4, 2);
using static System.Math;//注意这里不是命名空间哦

namespace My6Static
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine($"之前的使用方式: {Math.Pow(4, 2)}");
            Console.WriteLine($"导入后可直接使用方法: {Pow(4, 2)}");
        }
    }
}

枚举代码:

using static Desktop.Color;

namespace Desktop
{
    enum Color
    {
        Yellow,
        Red
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Yellow);
            Console.ReadKey();
        }
    }
}

4. 关于String.Format()方法的改进

return String.Format("({0}, {1})", X, Y);

return $"({0}, {1})", X, Y);

return $"({X}, {Y})";

5. 对于Lambda表达式的改进

许多方法主体只是一个简单的 return ,采用类似 Lambda 一样简洁的方法

ToString()函数可以改写成如下形式

public override string ToString() => $"({X}, {Y})";

public double Dist => Sqrt(X * X + Y * Y);

//之前
public double Dist
{
    get{return return Sqrt(X * X + Y * Y);}
}

5.1 简化代码对比

public class Point
    {
        public int X { get; } = 2;

        public int Y { get; set; } = 1;

        public double Dist => Sqrt(X * X + Y * Y);

        public override string ToString() => $"({X}, {Y})";
    }

//简化之前
public class Point
    {
        public int X { get; set; }

        public int Y { get; set; }

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

        public double Dist
        {
            get { return Math.Sqrt(X * X + Y * Y); }
        }

        public override string ToString()
        {
            return String.Format("({0}, {1})", X, Y);
        }
    }

6. 索引初始化

这是一种将点对象转化为 Json 对象的方法

你可以直接初始化对象初始值 设定项中的属性,但仍必须在单独的语句中分配这样的索引 setter。

C# 6.0 扩展对象初始值设定项,让你可以在 {} 里直接分配它们内部的索引

因此,可以在一个表达式中以声明的方式对 Json 对象进行初始化

这会带来简化这一级的联动效应,不再需要临时变量,一行代码

public JObject ToJson()
        {
            var result = new JObject();
            result["X"] = X;
            result["Y"] = Y;
            return result;
        }

改进后的代码可以这么写

public JObject ToJson()
        {
            var result = new JObject()
            {
                ["X"] = X,
                ["Y"] = Y
            };
            return result;
        }

最终可以化简成一行代码

public JObject ToJson() => new JObject() { ["X"] = X, ["Y"] = Y };

7. Null 条件运算符 – ?.

?.运算符其实很简单,主要就是检查变量是否为null,如果不为null那就执行.

先来看一个函数,这个判断语句中大部分的检查都是在

    public static Point FromJson(JObject json)
        {
            if (json != null &&
                json["X"] != null &&
                json["X"].Type == JTokenType.Integer &&
                json["Y"] != null &&
                json["Y"].Type == JTokenType.Integer
                )
            {
                return new Point((int)json["X"], (int)json["Y"]);
            }
            return null;
        }

这个函数可以用?.运算符化简成

    public static Point FromJson(JObject json)
        {
            if (json != null &&
                json["X"]?.Type == JTokenType.Integer &&
                json["Y"]?.Type == JTokenType.Integer
                )
            {
                return new Point((int)json["X"], (int)json["Y"]);
            }
            return null;
        }

意思是如果json[“x”]为null,那么就不执行. 如果json[“x”]不为null,那么就会执行.然后判断类型是否为int

所以代码可以被再次化简

    public static Point FromJson(JObject json)
        {
            if (json?["X"]?.Type == JTokenType.Integer &&
                json?["Y"]?.Type == JTokenType.Integer
                )
            {
                return new Point((int)json["X"], (int)json["Y"]);
            }
            return null;
        }

只有当接收方 json 不为空时才继续

7.2 依然是 ?.

在触发事件的时候

OnChanged(this, args);

如果此时OnChanged为空显然是不行的所以呢,可以改写成这样

if (OnChanged == null)
{
    OnChanged(this, args);
}

如果很不幸的另外一个线程就在判断之后,触发事件之前,再次设置OnChanged变为null,同样会导致错误

为了保证线程安全,需要先Copy一份,但是这样写显然就。。。

var onChanged = OnChanged;
if (onChanged != null)
{
   onChanged(this, args);
}

现在可以改写成这样

//null 传播运算符,只有委托不为null时才会调用
OnChanged?.Invoke(this, args);

8. Nameof 运算符

在对方法参数进行检查时经常这样写:

private static void Add(Account account)
{
     if (account == null)
         throw new ArgumentNullException("account");
}

如果某天参数的名字被修改了(用编译器自动重构的快捷键),下面的字符串很容易漏掉忘记修改.
使用nameof表达式后,编译的时候编译器将检查到有修改后自动导航与重构

private static void Add(Account account)
{
     if (account == null)
         throw new ArgumentNullException(nameof(account));
}

9. 异常刷选器 – 支持在catch和finally块中使用await

Resource res = null;
try
{
    res = await Resource.OpenAsync(…);       // You could do this.
    …
}
catch(ResourceException e)
{
    await Resource.LogAsync(res, e);         // Now you can do this …
}
finally
{
    if (res != null) await res.CloseAsync(); // … and this.
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值