C#7.0新特性学习

C#7.0引入了许多新特性,如输出(out)变量的简化,模式匹配允许更灵活的值检测,元组提供更优雅的多值返回方式,局部函数支持内部函数定义,Literal改进使数字可读性更强,以及ref局部变量和引用返回优化内存管理,还有广义异步返回类型提升性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

输出(out)变量

模式匹配

元组

局部函数

Literal 改进

Ref 本地和返回

ref locals(ref局部变量,也即本地)

ref  returns (ref引用返回)

广义异步返回类型

更多 Expression-bodied 方法


C#7.0语言增加了许多的新功能,促使专注于数据消费,简化代码和性能。

输出(out)变量

一个方法有多个返回值时,返回值类型相同可以返回一个数组。

 返回值类型不同时可以使用out

out参数:返回值多个,不限类型

注意事项:

  • 调用方法之前,对out参数传递的变量只需声明,可以赋值也可以不赋值,赋值也会在方法中被覆盖掉
  • 使用out参数传递变量时,必须在方法内为其赋值,否则return的返回值没有意义
  • 方法的参数使用out修饰时,调用该方法时也要加上out关键字
  • 使用out修饰的变量不需要return      
using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            int x;
            string y;

            Program.Method(out x,out y);

            Console.WriteLine(x+y);

            Console.ReadLine();
        }

        public static void Method(out int x,out string y)
        {
            x = 10;

            y = "hello";
        }
    }
}

结果:

 在C#7.0,我们增加了Out变量,作为out参数传递加入了声明变量权,如下。

using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            //int x;
            //string y;

            Program.Method(out int x,out string y);

            Console.WriteLine(x+y);

            Console.ReadLine();
        }

        public static void Method(out int x,out string y)
        {
            x = 10;

            y = "hello";
        }
    }
}

也即省略了声明变量的过程,运行结果同上。

模式匹配

C# 7.0 引入了模式的概念,抽象地说,这是一种语法成分可以用来测试一个值是否有一个一定的“形”以及在它起作用时从值里面获取到的额外信息。

C#从7.0开始,陆陆续续推出了各种模式匹配,模式是一种特殊的表达式,通过判断给定的值是否满足此表达式而返回true或者false,它就类似于正则表达式的作用。

部分使用方式如下。

Object value = "";
    if (value is string)
    {
        Console.WriteLine("value is String");
    }
    //输出:value is String

Object value = "String";
    if (value is string str)
    {
        Console.WriteLine($"value is {str}");
    }
    //输出:value is String

Object value = "String";
    if (value is "String")
    {
        Console.WriteLine($"value is String");
    }
    //输出:value is String

Object value = null;
    if (value is null)
    {
        Console.WriteLine($"value is null");
    }
    //输出:value is null

元组

这是常见的希望从一个方法返回多个值的做法。目前可用的选项不是最佳的:

  • Out 参数。使用笨拙(即便有上面描述到的提升),它们不使用异步的方法运行。
  • System.Tuple<...>  返回类型。使用累赘并且需要一个元组对象的分配。
  • 为每个方法定制传输类型:大量的代码为了类型开销的目的仅是临时收集一些值
  • 匿名类型通过返回一个 dynamic 返回类型。高性能开销并且没有静态类型检查。
using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            var data = new Tuple<string, int, char>("a",123,'c');

            Console.WriteLine(data.Item1);
            Console.WriteLine(data.Item2);
            Console.WriteLine(data.Item3);

            Console.ReadLine();
        }
    }
}

结果:

在C#7.0中,微软提供了更优雅的方案。

using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            var data = GetFullName();
            Console.WriteLine(data.a); //可用命名获取到值
            Console.WriteLine(data.b);
            Console.WriteLine(data.c);

            Console.ReadLine();
        }

        //方法定义为多个返回值,并命名
        private static (string a, string b, string c) GetFullName()
        {
            return ("a", "b", "c");
        }
    }
}

解构元组:有的时候我们不想用var匿名来获取,那么就可以通过解构的方式获取。

using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            (string a,int b,char c) = new Tuple<string, int, char>("a", 123, 'c');

            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(c);

            Console.ReadLine();
        }

    }
}

 结果如下:

也可以将数据类型放到括号外面如下。

var ( a, b, c) = new Tuple<string, int, char>("a", 123, 'c');

也可以通过解构赋值一个现有变量。

不仅仅元组可以被解构,任何类型都可以被解构,只要有一个对应的(实体或者扩展)解构方法即可。

局部函数

局部变量是指:只在特定过程或函数中可以访问的变量。

局部函数是指:只在特定的函数中可以访问的函数。

using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine(sum(100,200));

            Console.ReadLine();

            int sum(int x,int y)
            {
                return x + y;
            }
        }

    }
}

结果:

方法实现迭代器通常需要严格检查调用时非迭代器封装方法。(迭代器本身没有运行,只到调用MoveNext 才会运行)。局部函数在这种情况下是完美的。

如果迭代器是一个私有方法的下一个过滤器,它将有可能被其他成员不小心使用(没有参数检查)。此外,作为过滤器,它将需要采取所有的相同的参数,而不是指定域内的参数。

Literal 改进

在C#7.0中,允许数字中出现"_"这个分割符号,来提高可读性,例如:

    static void Main(string[] args)
        {
            int a = 123_456;

            Console.WriteLine(a);//输出结果是123456

            Console.ReadLine();
        }

因为是数字类型的,因此,decimal,float,double都可以这样分割。

        static void Main(string[] args)
        {
            int a = 123_456;
            float b = 123.456_789f;
            double c = 123.456_789;
            decimal d = 123.456_789M;
            int e = 0xABC_DEF;

            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(c);
            Console.WriteLine(d);
            Console.WriteLine(e);

            Console.ReadLine();
        }

在数字中使用“_”分隔符不会影响结果,只是为了提高可读性。

Ref 本地和返回

ref关键字是将值传递变为引用传递

ref locals(ref局部变量,也即本地)

static void Main(string[] args)
        {
            int x = 1;
            ref int y = ref x;//将x的引用(也就是地址)传给y
            y = 2;
            Console.WriteLine($"x={x}");//输出结果为x=2

            Console.ReadLine();
        }

这里通过ref关键字把x赋给了y,在给y赋值,如果是值类型的传递,那么x将不会改变。

在某些特定的场合,我们可以直接用ref来引用传递,减少了值传递所需要开辟的空间。

ref  returns (ref引用返回)

这个方式可以把值类型当作引用类型来进行return

        static void Main(string[] args)
        {
            int[] arr = { 1, 2, 3, 4, 5, 6 };

            ref int x = ref GetArrIndex(arr, 2);

            x = 123;

            Console.WriteLine($"arr[2]={arr[2]}");

            Console.ReadLine();

            ref int GetArrIndex(int[] arreray,int index)
            {
                return ref arreray[index];
            }
        }

结果:

通过ref返回引用类型,在重新赋值,arr数组中的值,相应也改变了。

注意:ref关键字很早就存在了,但是他只能用于参数,这次C#7.0让他不仅仅只能作为参数传递,还能作为本地变量和返回值了

广义异步返回类型

异步方法必须返回 void,Task 或 Task<T>,这次加入了新的ValueTask<T>,来防止异步运行的结果在等待时已可用的情境下,对 Task<T> 进行分配。对于许多示例中设计缓冲的异步场景,这可以大大减少分配的数量并显著地提升性能。

也即:在已经缓存的情况下,可以使用ValueTask来返回异步或者同步2种方案

更多 Expression-bodied 方法

C#6.0中,提供了对于只有一条语句的方法体可以简写成表达式。

public void Show() => new MyTest();
//等价于下面的代码
public void Show()
{
    new MyTest();
}

但是,并不支持用于构造函数,析构函数,和属性访问器,那么C#7.0就支持了。

    class MyTest
    {
        //get set 写法
        public string name
        {
            get => name;
            set => this.name=value ?? "name is null";
        }

        //构造函数表达式写法
        public MyTest(string name) => this.name = name;

        //析构函数表达式写法
        ~MyTest() => Console.WriteLine($"name={this.name}");
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值