2

C# 6.0 添加和增强的功能【基础篇】 - 橙子家

 1 year ago
source link: https://www.cnblogs.com/czzj/p/16822397.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client



C# 6.0 是在 visual studio 2015 中引入的。此版本更多关注了语法的改进,让代码更简洁且更具可读性,使编程更有效率,而不是和前几个版本一样增加主导性的功能。

一、静态导入

我们都知道,静态类中的方法是直接通过类名引用的。

例如:(Math 是系统自带的静态类,在程序中可以直接引用)

var num = Math.Sqrt(3*3 + 4*4);//取给定值的平方根

新写法:(分两步)

using static System.Console;
using static System.Math;// 1/2 在命名空间中,统一引用静态类

namespace Test.Test.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            WriteLine(Sqrt(3*3 + 4*4));// 2/2 直接调用方法,不用再带静态类名
        }
    }
}

using static 指令命名了一种类型,无需指定类型名称即可访问其静态成员和嵌套类型。

using static 仅导入可访问的静态成员和指定类型中声明的嵌套类型。 不导入继承的成员。

 二、异常筛选器

从 C# 6 开始,when 可用于 catch 语句中,以指定为执行特定异常处理程序而必须为 true 的条件。 语法为:

catch (ExceptionType [e]) when (expr)

 其中,expr 是一个表达式,其计算结果为布尔值。 如果该表达式返回 true,则执行异常处理程序;如果返回 false,则不执行。

具体用法示例:

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        Console.WriteLine(MakeRequest().Result);
    }
    public static async Task<string> MakeRequest()
    {
        var client = new HttpClient();
        var streamTask = client.GetStringAsync("https://localHost:10000");
        try
        {
            var responseText = await streamTask;
            return responseText;
        }
        catch (HttpRequestException e) when (e.Message.Contains("301"))
        {
            return "Site Moved";
        }
        catch (HttpRequestException e) when (e.Message.Contains("404"))
        {
            return "Page Not Found";
        }
        catch (HttpRequestException e)
        {
            return e.Message;
        }
    }
}

 三、自动属性初始化表达式

当需要将属性初始化为其类型默认值以外的值时,C# 通过在属性的右括号后设置值达到此目的。

对于 FirstName 属性的初始值,需要设置为空字符串而非 null。 可按如下所示进行指定:

public class Person
{
    public string FirstName { get; set; } = string.Empty;
}

或者自行定义存储:

public class Person
{
    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value; }
    }
    private string _firstName;
}

 四、Expression bodied 成员(表达式主体定义 =>)

 expression-bodied 方法包含单个表达式,它返回的值的类型与方法的返回类型匹配;或者,对于返回 void 的方法,其表达式则执行某些操作。常规语法:

member => expression;

例如,替代 ToString 方法的类型通常包含单个表达式,该表达式返回当前对象的字符串表示形式。

下面的示例定义 Person 类,该类通过表达式主体定义替代 ToString。 它还定义向控制台显示名称的 DisplayName 方法。

请注意,ToString 表达式主体定义中未使用 return 关键字。

using System;

public class Person
{
   public Person(string firstName, string lastName)
   {
      fname = firstName;
      lname = lastName;
   }

   private string fname;
   private string lname;

   public override string ToString() => $"{fname} {lname}".Trim();
   public void DisplayName() => Console.WriteLine(ToString());
}

class Example
{
   static void Main()
   {
      Person p = new Person("Mandy", "Dejesus");
      Console.WriteLine(p);
      p.DisplayName();
   }
}

 五、Null 传播器

仅当操作数的计算结果为非 NULL 时,NULL 条件运算符才对其操作数应用成员访问 或元素访问 ?. 操作;否则,它会返回 NULL。从而避免了空对象的报错:Object reference not set to an instance of an object。

NULL 条件运算符采用最小化求值策略。 也就是说,如果条件成员或元素访问运算链中的一个运算返回 null,则链的其余部分不会执行。

如下示例:

int GetSumOfFirstTwoOrDefault(int[] numbers)
{
    // ??(Null 合并操作符): 如果此运算符的左操作数不为 null,则此运算符将返回左操作数,否则返回右操作数
    if ((numbers?.Length ?? 0) < 2)
    {
        return 0;
    }
    return numbers[0] + numbers[1];
}

Console.WriteLine(GetSumOfFirstTwoOrDefault(null));  // output: 0
Console.WriteLine(GetSumOfFirstTwoOrDefault(new int[0]));  // output: 0
Console.WriteLine(GetSumOfFirstTwoOrDefault(new[] { 3, 4, 5 }));  // output: 7

六、字符串内插($"{}")

$ 特殊字符将字符串文本标识为内插字符串 。 内插字符串是可能包含内插表达式的字符串文本 。 将内插字符串解析为结果字符串时,带有内插表达式的项会替换为表达式结果的字符串表示形式。

要在内插字符串生成的文本中包含大括号 "{" 或 "}",请使用两个大括号,即 "{{" 或 "}}"。

因为冒号(":")在内插表达式项中具有特殊含义,为了在内插表达式中使用条件运算符,请将表达式放在括号内。

string name = "Horace";
int age = 34;
Console.WriteLine($"He asked, \"Is your name {name}?\", but didn't wait for a reply :-{{");
Console.WriteLine($"{name} is {age} year{(age == 1 ? "" : "s")} old.");
// Expected output is:
// He asked, "Is your name Horace?", but didn't wait for a reply :-{
// Horace is 34 years old.

七、nameof 表达式

nameof 表达式可生成变量、类型或成员的名称作为字符串常量:

Console.WriteLine(nameof(System.Collections.Generic));  // output: Generic
Console.WriteLine(nameof(List<int>));  // output: List
Console.WriteLine(nameof(List<int>.Count));  // output: Count
Console.WriteLine(nameof(List<int>.Add));  // output: Add
var numbers = new List<int> { 1, 2, 3 };
Console.WriteLine(nameof(numbers));  // output: numbers
Console.WriteLine(nameof(numbers.Count));  // output: Count
Console.WriteLine(nameof(numbers.Add));  // output: Add
//在逐字标识符的情况下,@ 字符不是名称的一部分,如以下示例所示:
var @new = 5;
Console.WriteLine(nameof(@new));  // output: new

nameof 表达式在编译时进行求值,在运行时无效。

八、 索引初始化表达式

 从本质来看,[xxx] = yyy 这种语法,xxx 可以是任意类型,凡是有索引器支持的类型,均可以使用这种语法。

private static void Main()
{
    var dictionary = new Dictionary<int, string>
    {
        [1] = "Value1",
        [2] = "Value2",
        [3] = "Value3"
    };
}

 九、Catch/Finally 块中的 Await

 Asyn 方法是一个现在很常用的方法,当使用 async 和 await 时,你或许曾有这样的经历,就是你想要在 catch 块或 finally 块中使用它们,比如当出现一个 exception 而你希望将日志记在文件或者调用一个服务将 exception 信息发送给 server,而这些操作可能很耗时。这种情况下,在 catch 块中的异步方法中使用 await 将会很有帮助。具体语法示例:

public async Task SubmitDataToServer()
{
    try
    {
    }
    catch
    {
        await LogExceptionAsync();
    }
    finally
    {
        await CloseConnectionAsync();
    }
}

 注:暂时整理这些,欢迎指正和补充。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK