C#7.0新特性的学习笔记

官方文档地址为C#7.0,下面是我的7.0学习笔记

out 变量

可以直接在参数中声明一个out变量,不需要单独的声明语句

		public static void Tout(out string a)
        {
            a = "a1";
        }

out和ref,ref更侧重于修改,而out则是输出,下面是一个out和ref的例子
ref还是需要新声明,而out可以直接在参数中写入,ref是有进有出,而out是只出不进

static void Main(string[] args)
        {
            string a = "";
            Tout(out string test1);
            Tref(ref a);
            Console.WriteLine(test1);
            Console.WriteLine(a);
            Console.ReadLine();
        }

        public static void Tout(out string a)
        {
            a = "a1";
        }

        public static void Tref(ref string b)
        {
            b = "b1";
        }

元组

官方的元组详细介绍文档地址元组

先介绍一下python中的元组
python中的几个集合,分别是
list列表,相当于C#中的list集合

list = [ 'a', 786 , 1, 'c', 88 ]

和C#一样支持按下标取值

dictionary字典

dict = {}
dict['one'] = "This is one"
dict[2] = "This is two"		
tinydict = {'name': 'john','code':6734, 'dept': 'sales'}

还有就是元组
python中的元组用 () 标识。内部元素用逗号隔开。但是元组不能二次赋值,相当于只读列表。

tuple = ( 'runoob', 786 , 2.23, 'john', 70.2 )	

下面再介绍一下C#7.0中的元组
元组是包含多个字段以表示数据成员的轻量级数据结构。

			(string a, string b) test = ("a", "b");
            Console.WriteLine($"{test.a}+{test.b}");
            test.a = "aa";
            Console.WriteLine($"{test.a}+{test.b}");

如上代码所示,C#中的元组允许修改。也可以给右侧的字段赋名称,并且声明多少就可以输入多少参数。

(string a, string b,string c) test = ("a", "b","c");

在进行元组赋值时,还可以指定赋值右侧的字段的名称:

 (string a, string b) testDicError = (key: "a", value: "b");//不支持这种赋命名 必须要var才能取到key value
            var testDic = (key:"a",value:"b");
            Console.WriteLine($"{testDic.key}+{testDic.value}");

重点来了,方法返回值可以返回元组类型,如下代码,这个真的是太好用了,返回元素还可以按照名称获取。

public static double StandardDeviation(IEnumerable<double> sequence)
{
    (int Count, double Sum, double SumOfSquares) computation = ComputeSumAndSumOfSquares(sequence);

    var variance = computation.SumOfSquares - computation.Sum * computation.Sum / computation.Count;
    return Math.Sqrt(variance / computation.Count);
}

private static (int Count, double Sum, double SumOfSquares) ComputeSumAndSumOfSquares(IEnumerable<double> sequence)
{
    var computation = (count: 0, sum: 0.0, sumOfSquares: 0.0);

    foreach (var item in sequence)
    {
        computation.count++;
        computation.sum += item;
        computation.sumOfSquares += item * item;
    }

    return computation;
}

弃元
人如其名,元组中不要的元素,想要丢弃,可以使用一个名为 _(下划线字符)的只写变量,知道就用,不知道就不丢弃该元素,多打一个命名,影响不大,语法使用如下。

using System;
using System.Collections.Generic;

public class Example
{
    public static void Main()
    {
        var (_, _, _, pop1, _, pop2) = QueryCityDataForYears("New York City", 1960, 2010);

        Console.WriteLine($"Population change, 1960 to 2010: {pop2 - pop1:N0}");
    }

    private static (string, double, int, int, int, int) QueryCityDataForYears(string name, int year1, int year2)
    {
        int population1 = 0, population2 = 0;
        double area = 0;

        if (name == "New York City")
        {
            area = 468.48;
            if (year1 == 1960)
            {
                population1 = 7781984;
            }
            if (year2 == 2010)
            {
                population2 = 8175133;
            }
            return (name, area, year1, population1, year2, population2);
        }

        return ("", 0, 0, 0, 0, 0);
    }
}

模式匹配

官方介绍如下:模式匹配 是一种可让你对除对象类型以外的属性实现方法分派的功能。模式匹配支持 if 表达式和 switch 表达式。
直接使用官方代码介绍吧,目前只支持if和switch看一下就懂了
if的代码if (input is int count) sum += count;
switch的代码

public static int SumPositiveNumbers(IEnumerable<object> sequence)
{
    int sum = 0;
    foreach (var i in sequence)
    {
        switch (i)
        {
            case 0:
                break;
            case IEnumerable<int> childSequence:
            {
                foreach(var item in childSequence)
                    sum += (item > 0) ? item : 0;
                break;
            }
            case int n when n > 0:
                sum += n;
                break;
            case null:
                throw new NullReferenceException("Null found in sequence");
            default:
                throw new InvalidOperationException("Unrecognized type");
        }
    }
    return sum;
}

Ref 局部变量和返回结果

直接举例子吧

using System;

class NumberStore
{
    int[] numbers = { 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023 };

    public ref int FindNumber(int target)
    {
        for (int ctr = 0; ctr < numbers.Length; ctr++)
        {
            if (numbers[ctr] >= target)
                return ref numbers[ctr];
        }
        return ref numbers[0];
    }

    public override string ToString() => string.Join(" ", numbers);
}
var store = new NumberStore();
Console.WriteLine($"Original sequence: {store.ToString()}");
int number = 16;
ref var value = ref store.FindNumber(number);
value *= 2;
Console.WriteLine($"New sequence:      {store.ToString()}");
// The example displays the following output:
//       Original sequence: 1 3 7 15 31 63 127 255 511 1023
//       New sequence:      1 3 7 15 62 63 127 255 511 1023

本地函数

个人理解可以在方法内声明一个方法使用,

public static IEnumerable<char> AlphabetSubset3(char start, char end)
{
    if (start < 'a' || start > 'z')
        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    if (end < 'a' || end > 'z')
        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

    if (end <= start)
        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");

    return alphabetSubsetImplementation();

    IEnumerable<char> alphabetSubsetImplementation()
    {
        for (var c = start; c < end; c++)
            yield return c;
    }
}

可以对 async 方法采用相同的技术,以确保在异步工作开始之前引发由参数验证引起的异常:

public Task<string> PerformLongRunningWork(string address, int index, string name)
{
    if (string.IsNullOrWhiteSpace(address))
        throw new ArgumentException(message: "An address is required", paramName: nameof(address));
    if (index < 0)
        throw new ArgumentOutOfRangeException(paramName: nameof(index), message: "The index must be non-negative");
    if (string.IsNullOrWhiteSpace(name))
        throw new ArgumentException(message: "You must supply a name", paramName: nameof(name));

    return longRunningWorkImplementation();

    async Task<string> longRunningWorkImplementation()
    {
        var interimResult = await FirstWork(address);
        var secondResult = await SecondStep(index, name);
        return $"The results are {interimResult} and {secondResult}. Enjoy.";
    }
}

throw 表达式

从 C# 7.0 开始,throw 可以用作表达式和语句。 这允许在以前不支持的上下文中引发异常。 这些方法包括:
**条件运算符。**下例使用 throw 表达式在向方法传递空字符串数组时引发 ArgumentException。 在 C# 7.0 之前,此逻辑将需要显示在 if/else 语句中。

private static void DisplayFirstNumber(string[] args)
{
   string arg = args.Length >= 1 ? args[0] :
                              throw new ArgumentException("You must supply an argument");
   if (Int64.TryParse(arg, out var number))
      Console.WriteLine($"You entered {number:F0}");
   else
      Console.WriteLine($"{arg} is not a number.");
}

null 合并运算符。 在以下示例中,如果分配给 Name 属性的字符串为 null,则将 throw 表达式与 null 合并运算符结合使用以引发异常。

public string Name
{
    get => name;
    set => name = value ??
        throw new ArgumentNullException(paramName: nameof(value), message: "Name cannot be null");
}

通用的异步返回类型

直接看链接Understanding the Whys, Whats, and Whens of ValueTask

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>