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选项,能让编译器每次生成完全一致的二进制输出

猜你喜欢

转载自www.cnblogs.com/mosakashaka/p/12608195.html