백엔드 개발 C#.Net 튜토리얼 C# 7.0의 새로운 언어 기능

C# 7.0의 새로운 언어 기능

Apr 29, 2017 pm 05:26 PM

​다음은 C# 7.0 언어의 Planning 기능에 대한 설명입니다. 이러한 기능은 대부분 Visual Studio "15" Preview 4에서 작동합니다. 지금이 바로 시험해 볼 수 있는 가장 좋은 시기이니, 여러분의 생각을 기록해 주세요.

C# 7.0 언어에는 데이터 소비, 단순화된 코드 및 성능에 초점을 맞춘 많은 새로운 기능이 추가되었습니다.

아마도 가장 큰 특징은 튜플일 것입니다. 이는 여러 결과를 쉽게 얻을 수 있게 하고 그에 따라 코드를 단순화합니다. 이는 데이터 모양에 따른 조건부 패턴 일치입니다. 그러나 코드를 보다 효율적이고 명확하게 실행하여 더 많은 창의성을 발휘할 수 있도록 결합하고 싶은 다른 기능도 많이 있습니다. 원하는 대로 실행되지 않는 부분이 있거나 개선하고 싶은 기능이 있는 경우 Visual Studio 창 상단의 "피드백 보내기" 기능을 사용하여 결과를 피드백해 주세요. 제가 설명한 많은 기능은 아직 Preview 4에서 완벽하게 작동하지 않으며, 사용자 피드백을 바탕으로 최종 버전이 출시되면 몇 가지 새로운 기능을 추가할 예정입니다. 최종 버전에서는 기존 계획의 일부 기능이 변경되거나 취소될 수 있다는 점을 지적해야 합니다.

이 기능 세트에 관심이 있고 배우고 싶다면 Roslyn GitHub 사이트에서 다양한 디자인 지침과 관련 토론을 찾을 수 있습니다.

출력변수

현재 C#에서는 out 매개변수를 사용하는 것이 생각만큼 원활하지 않습니다. out 매개변수가 있는 메소드를 호출할 때 먼저 전달할 변수를 선언해야 합니다. 일반적으로 이러한 변수를 초기화하지 않거나(나중에 메소드에 의해 덮어쓰기됨) VAR을 사용하여 선언할 수 없지만 전체 유형을 지정해야 합니다.

public void PrintCoordinates(Point p)
{    int x, y; // have to "predeclare"
    p.GetCoordinates(out x, out y);
    WriteLine($"({x}, {y})");
}
로그인 후 복사

C# 7.0에서는 변수를 선언하기 위해 out 매개 변수로 전달되는 지점인 Out 변수를 추가했습니다.

public void PrintCoordinates(Point p)
{
    p.GetCoordinates(out int x, out int y);
    WriteLine($"({x}, {y})");
}
로그인 후 복사

변수는 둘러싸는 블록의 범위 내에 있으므로 나중에 사용할 수 있습니다. 대부분의 문 유형은 자체 범위를 설정하지 않으므로 out 변수는 일반적으로 선언의 바깥쪽 범위에 도입됩니다.

참고: Preview 4에서는 범위 규칙이 더 엄격합니다. out 변수의 범위는 해당 변수가 선언된 문입니다. 따라서 위의 예는 이후 버전에서는 사용되지 않습니다.

out 변수는 out 매개 변수에 전달되는 인수로 직접 선언되므로 컴파일러는 일반적으로 (충돌하는 오버로드가 없는 한) 유형을 알 수 있습니다. 따라서 유형 대신 VAR을 사용하여 선언하는 것이 좋습니다.

p.GetCoordinates(out var x, out var y);
로그인 후 복사

out 매개변수의 일반적인 용도는 Try... 모드입니다. 이 모드에서는 out 매개변수의 부울 반환이 성공을 나타내며 out 매개변수로 얻은 결과는 다음과 같습니다.

public void PrintStars(string s)
{    if (int.TryParse(s, out var i)) { WriteLine(new string('*', i)); }    else { WriteLine("Cloudy - no stars tonight!"); }
}
로그인 후 복사

참고: Preview 4에서는 if 문으로 정의하여 이를 더 잘 처리합니다.

중요하지 않은 출력 매개변수를 무시하고 * 형식뿐 아니라 출력 매개변수로도 "와일드카드"를 허용하도록 계획하세요.

p.GetCoordinates(out int x, out *); // I only care about x
로그인 후 복사

참고: 와일드카드를 사용하여 C# 7.0으로 변환할 수 있는지 여부는 아직 알려지지 않았습니다.

패턴 매칭

C# 7.0에서는 모드 라는 개념을 도입했습니다. 추상적으로 말하면 이는 값이 특정 "모양"을 갖고 있는지 여부와 해당 값이 작동할 때 무엇을 얻는지 테스트하는 데 사용할 수 있는 문법적 구성 요소입니다. .

​다음은 C# 7.0의 패턴 예입니다.

  • c의 상수 모드(c는 C#의 상수 표현식)는 입력 매개변수가 c와 같은지 테스트하는 데 사용됩니다.


  • T x (T는 유형이고 x는 식별자)의 유형 패턴은 입력 매개변수의 유형이 T인지 테스트하는 데 사용됩니다. 그렇다면 입력 매개변수의 값을 T 유형의 새로운 x 변수로 추출합니다.


  • var x 변수 패턴(x는 식별자), 일반적으로 입력 매개변수의 값을 일치시키고 단순히 새 변수 x

에 넣습니다. 이것이 시작입니다. 패턴은 새로운 C# 언어 요소이며 앞으로 C#에 더 많은 패턴을 추가할 수 있습니다.

C# 7.0에서는 패턴을 사용하여 두 가지 기존 언어 구조를 향상합니다.

  • is 표현식은 이제 단순한 유형 대신 오른쪽에 패턴을 가질 수 있습니다.


  • 이제 switch 문의 case 절을 ​​상수 값뿐만 아니라 패턴으로 일치시킬 수 있습니다. ​​

C#의 미래에는 패턴을 사용할 수 있는 위치가 더 많이 추가될 수 있습니다.

패턴으로 표현인가요

​다음은 상수 패턴 및 유형 패턴과 함께 is 표현식을 사용하는 예입니다.

public void PrintStars(object o)
{    if (o is null) return;     // constant pattern "null"    if (!(o is int i)) return; // type pattern "int i"
    WriteLine(new string('*', i));
}
로그인 후 복사

  正如你所看到的,模式变量(变量通过模式引入)与先前描述的 out 变量有些类似,他们可以在表达式中被声明,而且可以在它们最近的周围范围内被使用。也像 out 变量那样,模式变量是易变的,

: 就像 out 变量一样,严格的范围规则适用于 Preview 4.

  模式和 Try 方法通常会一起出现:

if (o is int i || (o is string s && int.TryParse(s, out i)) { /* use i */ }
로그인 후 복사

  带模式的 Switch 语句

  我们正在泛化 switch 语句,因此:

  • 你可以在任何类型上使用 switch(不仅仅是原始类型)


  • 可以在 case 子句中使用模式


  • Case 子句可以拥有额外的条件

  这里是一个简单的例子:

switch(shape)
{
    case Circle c:
        WriteLine($"circle with radius {c.Radius}");
        break;
    case Rectangle s when (s.Length == s.Height):
        WriteLine($"{s.Length} x {s.Height} square");
        break;
    case Rectangle r:
        WriteLine($"{r.Length} x {r.Height} rectangle");
        break;
    default:
        WriteLine("<unknown shape>");
        break;
    case null:
        throw new ArgumentNullException(nameof(shape));
}
로그인 후 복사

  有几件关于这个新扩展的 switch 语句的事需要注意:

  • case 子句的顺序现在很重要:就像 catch 子句,case 子句不再是必然不相交的,第一个子句匹配的将被选择。因此这里重要的是上面代码中 square case 比 rectangle case 来得要早。也是和 catch 子句一样,编译器会通过标记明显不能到达的情况来帮助你。在这之前,你永远无法知道评价的顺序,所以这不是一个重大改变的特性。


  • 默认子句总是最后被评价:即使上面代码中 null 子句是最后才来,它会在默认子句被选择前被检查。这是为了与现有 switch 语义相兼容。然而,好的做法通常会让你把默认子句放到最后。


  • null 子句在最后不可到达:这是因为类型模式遵循当前的 is 表达式的例子并且不会匹配空值。这保证了空值不会偶然被任何的类型模式捎来第一抢购。你必须更明确如何处理它们(或为默认子句留下他们)。

  通过 case ...: 标签引入的模式变量仅存在于相对应的 switch 部分的范围内。

  元组

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

  • Out 参数。使用笨拙(即便有上面描述到的提升),它们不使用异步的方法运行。


  • System.Tuple<...> 返回类型。使用累赘并且需要一个元组对象的分配。


  • 为每个方法定制传输类型:大量的代码为了类型开销的目的仅是临时收集一些值


  • 匿名类型通过返回一个 dynamic 返回类型。高性能开销并且没有静态类型检查。

  为了在这方面做得更好,C# 添加了tuple types tuple literals:

(string, string, string) LookupName(long id) // tuple return type
{
    ... // retrieve first, middle and last from data storage
    return (first, middle, last); // tuple literal
}
로그인 후 복사

  这个方法目前有效地返回三个字符串,将其作为元素在元组类型里包裹起来。

  方法的调用者将会接受到一个元组,并且可以逐一访问元素。

var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");
로그인 후 복사

  Item1 等等,是元组元素的默认名字,并能够经常被使用。但它们不是太好描述的,因此你可以选择性地添加更好的一个。

(string first, string middle, string last) LookupName(long id) // tuple elements have names
로그인 후 복사

  现在元组的接受者拥有更多的可描述的名字用于运行:

var names = LookupName(id);
WriteLine($"found {names.first} {names.last}.");
로그인 후 복사

  你也可以在 tuple literals 中直接指定名字:

return (first: first, middle: middle, last: last); // named tuple elements in a literal
로그인 후 복사

  通常来说,你可以互相分配元组类型无关的名字,只要独立的元素是可以被分配的,元组类型会自如 转换成其他元组类型。特别是对于 tuple literals ,存在一些限制,这会警告或提示在常见的错误的情况下提示,例如偶然交换元素的名字。

注意:这些限制还没在 Preview 4 中实现

  元组是值类型,而且他们的元素只是公开、易变的域。他们的值相等,代表这两个元组是相等的(都有相同的哈斯码)如果它们的元素都结对匹配(都有相同的哈斯码)。

  这使得元组对于在多种返回值下的很多情况十分有用。举例来说,如果你需要一个有多种键的词典,使用元组作为你的键,然后一切东西就会如常工作。如果你需要在每个位置有一个有多种值的列表,使用元组,查找列表等等,程序会正常运行。

注意:元组依赖一系列底层类型,它们在 Preview 4 中不被引入。为了将来的工作,你可以通过 NuGget 轻易获取它们: 在 Solution Explorer 中右键点击项目,并选择“Manage NuGet Packages…” 选择“Browse”选项卡,检查“Include prerelease” 并且选择“nuget.org”作为“Package source” 搜索“System.ValueTuple”并安装它

  解构

  另一种消除元组(tuple)的方法是解构元组。通过一个解构声明语法,把一个元组(或者其他的值)拆分为几部分,并且重新定义为新的变量。

(string first, string middle, string last) = LookupName(id1); // deconstructing decla
rationWriteLine($"found {first} {last}.");
로그인 후 복사

  在解构中可采用var关键字:

(var first, var middle, var last) = LookupName(id1); // var inside
로그인 후 복사

  或者把var关键字提取出来,在括号外:

var (first, middle, last) = LookupName(id1); // var outside
로그인 후 복사

  你也可以通过解构赋值来解构一个现有变量:

(first, middle, last) = LookupName(id2); // deconstructing assignment
로그인 후 복사

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

public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }
로그인 후 복사

  输出参数由解构之后的结果值构成。

  (为什么采用数据参数代替返回一个元组?这样,你可以重载多个不同的数值)

class Point
{
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y) { X = x; Y = y; }
    public void Deconstruct(out int x, out int y) { x = X; y = Y; }
}

(var myX, var myY) = GetPoint(); // calls Deconstruct(out myX, out myY);
로그인 후 복사

  这将成为一种常见模式,包含析构函数和“对称”解析:

  针对输出变量,我们计划在解构中允许使用“通配符”:

(var myX, *) = GetPoint(); // I only care about myX
로그인 후 복사
注:仍然还没有确定是否将通配符引入C# 7.0中。

  局部函数

  有时,一个辅助函数只在一个使用它的单一方法内部有意义。现在你可以在其他功能体内部声明这些函数作为一个局部函数:

public int Fibonacci(int x)
{
    if (x < 0) throw new ArgumentException("Less negativity please!", nameof(x));
    return Fib(x).current;

    (int current, int previous) Fib(int i)
    {
        if (i == 0) return (1, 0);
        var (p, pp) = Fib(i - 1);
        return (p + pp, p);
    }
}
로그인 후 복사

  参数和闭合区间局部变量可用在局部函数内,类似lambda表达式。

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

public IEnumerable<T> Filter<T>(IEnumerable<T> source, Func<T, bool> filter)
{
    if (source == null) throw new ArgumentNullException(nameof(source));
    if (filter == null) throw new ArgumentNullException(nameof(filter));

    return Iterator();

    IEnumerable<T> Iterator()
    {
        foreach (var element in source) 
        {
            if (filter(element)) { yield return element; }
        }
    }
}
로그인 후 복사

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

注:在Preview 4版本中,本地函数必须在它们被调用之前声明。这个限制将被放松,能调用读取直接赋值的局部变量。

  Literal 改进

  C# 7.0 允许使用“_”作为数字分隔符在数字literals中:

var d = 123_456;
var x = 0xAB_CD_EF;
로그인 후 복사

  你可以把它放在你想要的位置,提升可读性。这样对数值没有任何影响。

  此外,C# 7.0也介绍了二进制literals,这样你可以直接指定二进制模式而不必知道十六进制符号。

var b = 0b1010_1011_1100_1101_1110_1111;
로그인 후 복사

  Ref 返回和本地

  就像你可以通过reference(用ref修饰符)在C#中传递东西,您现在可以通过reference return 他们,并通过 reference将它们存储在局部变量中。

public ref int Find(int number, int[] numbers)
{
    for (int i = 0; i < numbers.Length; i++)
    {
        if (numbers[i] == number) 
        {
            return ref numbers[i]; // return the storage location, not the value
        }
    }
    throw new IndexOutOfRangeException($"{nameof(number)} not found");
}

int[] array = { 1, 15, -39, 0, 7, 14, -12 };
ref int place = ref Find(7, array); // aliases 7&#39;s place in the array
place = 9; // replaces 7 with 9 in the array
WriteLine(array[4]); // prints 9
로그인 후 복사

  这对绕过占位符成为大数据结构是非常有用的。举例来说,一个游戏可能会在一个大的预分配数组结构中保存其数据(为避免垃圾收集暂停)。Methods 可以直接返回一个 reference 到这样一个结构,且通过调用者可以读取和修改它。

  这里有一些限制,以确保这是安全的:

  • 你可以只返回 refs 那些是 “安全返回(safe to return)”的:那些被传递给你的,和那些点到对象的字段。


  • Ref locals被初始化为某一存储位置,并且不能突变到指向另一个。

  广义异步返回类型

  截至目前为止,在C#调用异步方法必须要返回void,Task或Task。C#7.0允许以这样的方式来定义其它类型,从而使它们可以从异步方法返回。

  例如,我们计划有一个ValueTask结构类型。它是建立在预防Task 对象的分配时,异步操作的结果是已在可等候的时间的情况下。对于很多异步场景,比如以涉及缓冲为例, 这可以大大减少分配的数量,并使性能有显著提升。

  这里有许多其他的方法可以让您想象自定义“task-like”类型是有用的。它不会是简单的正确创建,所以我们不要指望大多数人推出自己的,但他们很可能将会开始在框架和API展现出来,然后调用方可以返回并await他们今天做任务(Tasks)的方式。

注:广义异步返回类型尚未应用在预览4。

  更多 Expression-bodied 方法

  Expression-bodied 方法、属性等都是C# 6.0的重大突破,但并不允许他们在各种各样的member中使用,C#7.0添加了访问器、构造函数和终结器等,使更多member可以使用Expression-bodied 方法:

class Person
{
    private static ConcurrentDictionary<int, string> names = new ConcurrentDictionary<int, string>();
    private int id = GetId();

    public Person(string name) => names.TryAdd(id, name); // constructors
    ~Person() => names.TryRemove(id, out *);              // destructors
    public string Name
    {
        get => names[id];                                 // getters
        set => names[id] = value;                         // setters
    }
}
로그인 후 복사
注:这些额外的Expression-bodied 方法还没有工作在预览4。

  这是一个由社区贡献的特征,而非微软C#团队。并且,开源!

  在表达式的中间抛出一个异常是很容易的,只需要为你自己调用一个方法,但在C#7.0中我们允许在一些地方直接抛出表达式:

class Person
{
    public string Name { get; }
    public Person(string name) => Name = name ?? throw new ArgumentNullException(name);
    public string GetFirstName()
    {
        var parts = Name.Split(" ");
        return (parts.Length > 0) ? parts[0] : throw new InvalidOperationException("No name!");
    }
    public string GetLastName() => throw new NotImplementedException();
}
로그인 후 복사
  注:抛出表达式还未在预览4工作。

  本文地址:http://www.oschina.net/translate/whats-new-in-csharp-7-0

  原文地址:https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/

위 내용은 C# 7.0의 새로운 언어 기능의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

C#을 사용한 Active Directory C#을 사용한 Active Directory Sep 03, 2024 pm 03:33 PM

C#을 사용한 Active Directory 가이드. 여기에서는 소개와 구문 및 예제와 함께 C#에서 Active Directory가 작동하는 방식에 대해 설명합니다.

C#의 난수 생성기 C#의 난수 생성기 Sep 03, 2024 pm 03:34 PM

C#의 난수 생성기 가이드입니다. 여기서는 난수 생성기의 작동 방식, 의사 난수 및 보안 숫자의 개념에 대해 설명합니다.

C#의 액세스 한정자 C#의 액세스 한정자 Sep 03, 2024 pm 03:24 PM

C#의 액세스 수정자에 대한 안내입니다. 예제 및 출력과 함께 C#의 액세스 한정자의 소개 유형에 대해 논의했습니다.

C# 데이터 그리드 보기 C# 데이터 그리드 보기 Sep 03, 2024 pm 03:32 PM

C# 데이터 그리드 뷰 가이드. 여기서는 SQL 데이터베이스 또는 Excel 파일에서 데이터 그리드 보기를 로드하고 내보내는 방법에 대한 예를 설명합니다.

C# 직렬화 C# 직렬화 Sep 03, 2024 pm 03:30 PM

C# 직렬화 가이드. 여기에서는 C# 직렬화 개체의 소개, 단계, 작업 및 예제를 각각 논의합니다.

C#의 패턴 C#의 패턴 Sep 03, 2024 pm 03:33 PM

C#의 패턴 가이드. 여기에서는 예제 및 코드 구현과 함께 C#의 패턴 소개 및 상위 3가지 유형에 대해 설명합니다.

C#의 소수 C#의 소수 Sep 03, 2024 pm 03:35 PM

C#의 소수 가이드. 여기서는 코드 구현과 함께 C#의 소수에 대한 소개와 예를 논의합니다.

C#의 팩토리얼 C#의 팩토리얼 Sep 03, 2024 pm 03:34 PM

C#의 팩토리얼 가이드입니다. 여기서는 다양한 예제 및 코드 구현과 함께 C#의 계승에 대한 소개를 논의합니다.

See all articles