温故之C# 便捷语法一

本文包含如下便捷语法:express

  • 属性在声明处便可进行初始化
  • Expression-bodied 函数成员
  • using static加强功能
  • Null 条件运算符?. ??
  • 字符串的格式化
  • 异常筛选器
  • nameof 表达式
  • Catch 和 Finally 块中的 Await

属性在声明处便可进行初始化

在声明它的位置处被初始化。 这样,就能更容易地仅执行一次初始化。 以下:安全

public string FeatureOne { get; } = "NewFeature_One";
public ICollection<double> Grades { get; } = new List<double>();
public string AutoInit { get; set; } = "Auto Init";
复制代码

Expression-bodied 函数成员

当咱们编写的函数主体只包含一条能够表示为表达式的语句时,可经过改成编写 expression-bodied 成员来简化该语法。 好比:微信

public override string ToString() => $"{LastName}, {FirstName}";
复制代码

还能够在只读属性中使用 expression-bodied 成员:(如下语句将会被编译成只读属性)async

public string FullName => $"{FirstName} {LastName}";
// Expression-bodied get / set accessors.
public string Label {
    get => label;
    set => this.label = value ?? "Default label";
}
复制代码

using static加强功能

using static 加强功能可用于导入单个类的静态方法。 之前,using 语句将全部类型导入命名空间中。 好比,咱们只须要使用System命名空间下的Math类,其余的类咱们并不使用,此时咱们能够经过如下方式引入Math类ide

using static System.Math;
复制代码

经过这种方式引入后,使用方式也与以前有必定的变化,以下:函数

// 以前的使用方式
Math.Abs(1 + 2.5);
// 使用 using static System.Math;以后的方式
Abs(1 + 2.5);
复制代码

切记,这种引入方式只会引入该声明类中的静态方法。引入后的静态方法可当成全局函数使用,但其做用范围须要分为文件顶部引入和命名空间内部引入(参见温故之C# using注意事项工具

Null 条件运算符?. ??

?.运算符

在代码中,为了保证每一个引用不会抛出NullException异常,咱们每每须要进行以下判断:this

Feature feature = GetFeature();
if(tmpValue != null) {
  Console.WriteLine(feature.ToString());
}
复制代码

而有了 Null 条件运算符以后,咱们的写法可简化为以下feature?.ToString()编码

Feature feature = GetFeature();
Console.WriteLine(feature?.ToString());
复制代码

相信,此运算符在事件判断上更是会普遍使用,好比有Saved事件,如今,咱们能够以更加简洁且更加线程安全的方式访问了,以下spa

Saved?.Invoke(this, eventArgs);
复制代码
??运算符

此运算符可保证在没有合法值之时,为变量提供一个默认值。 在以前,是这样的:

string obj = null;
string res = string.Empty;
if (obj == null) {
  obj = "this is default value";
}else {
  res = obj;
}
Console.WriteLine(res);
复制代码

而如今,是这样的:

string obj = null;
string res = obj ?? "this is default value";
Console.WriteLine(res);
复制代码

看,如今是否是简洁了不少呢?另外,若是须要抛出异常,则能够按如下方式:

string obj = null;
string res = obj ?? throw new ArgumentNullException(paramName: nameof(obj), message: "must not be null");
Console.WriteLine(res);
复制代码

字符串的格式化

在以前,咱们格式化字符串方式以下:

string tmp = string.Format("{0} {1}", FirstName, LastName);
复制代码

如今,咱们能够以更加方便的方式处理:

string tmp = $"{FirstName} {LastName}";
复制代码

不知道您是否发现了它的优点?除了比以前更加简洁以外,更重要的是,当须要格式化的参数不少(好比5个以上时),很容易将这些参数的顺序混淆,而如今,您所写的,就是它存在的顺序,减小了出错的几率(甚至根本不会出错)。

异常筛选器

异常筛选器是肯定什么时候应该应用给定的 catch 子句的子句。若是用于异常筛选器的表达式计算结果为 true,则 catch 子句将对异常执行正常处理。 若是表达式计算结果为 false,则将跳过 catch 子句。使用方式以下:

public static async Task<string> MakeRequest() { 
    var client = new System.Net.Http.HttpClient();
    var streamTask = client.GetStringAsync("https://localHost:10000");
    try {
        var responseText = await streamTask;
        return responseText;
    } catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
    {
        return "Site Moved";
    }
}
复制代码

nameof 表达式

nameof 表达式的计算结果为符号的名称。 每当须要变量、属性或成员字段的名称时,这是让工具正常运行的好办法。 nameof 的其中一个最多见的用途是提供引发异常的符号的名称,以下:

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

这样写有个好处就是,假如咱们须要使用重构工具重命名符号, 更改lastNamefirstName,则会在 nameof 表达式中对其重命名。而字符串硬编码的方式则没有这一优点,很容易被忽略。

若是您写过WPF程序,那么您确定使用过INotifyPropertyChanged, 以前要实现属性更改的通知功能,实现方式以下:

public string LastName {
    get { return lastName; }
    set {
        if (value != lastName) {
            lastName = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LastName"));
        }
    }
}
private string lastName;
复制代码

而如今,PropertyChangedEventArgs的参数,可以使用nameof(LastName):

public string LastName {
    get { return lastName; }
    set {
        if (value != lastName) {
            lastName = value;
            PropertyChanged?.Invoke(this, 
                new PropertyChangedEventArgs(nameof(LastName)));
        }
    }
}
private string lastName;
复制代码

Catch 和 Finally 块中的 Await

catch 表达式中使用 await,这一般用于日志记录方案。以下:

public static async Task<string> MakeRequestAndLogFailures() { 
    await logMethodEntrance();
    var client = new System.Net.Http.HttpClient();
    var streamTask = client.GetStringAsync("https://localHost:10000");
    try {
        var responseText = await streamTask;
        return responseText;
    } catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301")) {
        await logError("Recovered from redirect", e);
        return "Site Moved";
    } finally {
        await logMethodExit();
        client.Dispose();
    }
}
复制代码

不过,我的还没有发现此记录方式的优点,暂不推荐使用。通常地,在项目中须要记录日志,会采用单独的服务来处理日志,即有异常时,当即将异常信息发送给日志记录服务,而程序自己继续下一步。使用的较多的是采用Kafka来进行日志的记录,关于Kafka,您能够百度,若是还有疑惑,咨询我也能够。

至此,本节内容讲解完毕,欢迎您来探讨!我的微信二维码以下:

我的微信二维码
相关文章
相关标签/搜索