C의 새로운 기능 # 8.0

마이크로 채널 대중 번호 : FINTECH 괴짜
소프트웨어 개발 엔지니어, 금융 정보 기술 회사에서 작업의 CFA를 통해 지식과 기술을 결합하여 컴퓨터와 금융 부문의 공유.

C의 새로운 기능 # 8.0

C # 8.0은 오랜 시간에 시작되었습니다, 체결되지 않은 전에이 회사는 오늘날 주요 내용보기 및 테스트 마이크로 소프트 공식 문서 버전 6.0, 플러스 개인적인 일을 사용하여 주로하기 때문에 : HTTPS를 : // 문서를 .microsoft.com을 / EN-US는 / DOTNET / CSHARP / 무슨 새로운 /의 CSHARP-8

읽기 전용 회원 (읽기 전용 회원)

구조체 읽기 전용 구조체는 불변 나타내는 정면에서, 모든 특성은 읽기 전용이어야 포함 플러스. 읽기 전용 부재 것이보다 정밀하게 제어하므로 어느 프로그래머는 읽기 전용으로 설정되어있는 부재를 지정할 수 있다는 것을 의미한다. 다음은 샘플 코드는 다음과 같습니다

    public struct ReadonlyMembers
    {
        public double X { get; set; }
        public double Y { get; set; }
        public double Z { get; set; }
        public double Distance => Math.Sqrt(X * X + Y * Y + Z * Z);

        public readonly override string ToString() => $"({X}, {Y},{Z}) is {Distance} from the origin";

        public readonly void TestReadOnly()
        {
            //X = 10;//Complier error: Cannot assign to 'X' because it is read-only
        }
    }

ToString 및 TestReadOnly : 위의 코드는 읽기 전용 두 가지 기능을 수정 포함한다. 당신이 할당 X하려고하면 TestReadOnly에서, 컴파일러는 오류 메시지 주석을 제공 할 것입니다.
또한, ToString이 컴파일 거리 경고 :. 비 읽기 전용으로 CS8656 전화에 사용 의 암시 사본에 '읽기 전용'멤버 결과에서 멤버 'ReadonlyMembers.Distance.get' '이' 컴파일러는하지 않기 때문에 GET가 상태를 변경하지 않습니다 생각 구조체는 거리 표시가 읽기 전용으로 설정해야합니다,하지만 당신은 자동으로 속성이 필요하지 않습니다, 컴파일러가 된 toString 액세스 X, Y, Z 회원 있도록 상태를 수정하기 위해 액세스 할 수 없습니다 생각합니다 그것은 컴파일러 경고가 발생하지 않습니다.

기본 인터페이스 방법 (기본 인터페이스 방법)

이전 버전의 인터페이스는 부분적으로 달성 포함 할 수 없습니다, 그래서 한때,이 인터페이스가 필요합니다 구현이 수정 될 것을, 인터페이스에있는 모든 장소를 새 멤버를 추가하고이 새로운 기능은 새 멤버의 추가가 달성하기 위해 자신의 시간을 제공 할 수 있습니다 그러한 어떤 수정이 인터페이스를 구현하는 데 필요하지 않습니다 곳. 주의 할 점은 인터페이스의 구현이 유형을 달성하는 데 사용할 수 없습니다 수 있도록 사용 인터페이스 유형에, 인터페이스 호출을 구현할 때, 유산으로하지 않고 클래스 상속과 같은 인터페이스를 구현합니다. 참고 :이 기능은 닷넷 Framewok4.8, 아래의 컴파일러 오류에서 지원되지 않으며, 닷넷 코어 3.0에서 지원됩니다.

닷넷 프레임 워크 오류

여기에 기본 인터페이스의 예입니다 :

    public interface ICustomer
    {
        string Name { get; set; }

        int OrderCount { get; set; }

        public string GetOrderCount();

        public string GetName()//default implemented method
        {
            return Name;
        }

        protected void PrintName()
        {
            Console.WriteLine("Name:" + Name ?? "");
        }

        private void DummyPrivateMethod()
        {
            Console.WriteLine("Name:" + Name ?? "");
        }
    }

    public class FintechCustomer : ICustomer
    {
        public string Name { get; set; }
        public int OrderCount { get; set; } = 100;

        public string GetOrderCount()
        {
            return $"FintechCustomer order count:{OrderCount}";
        }

        public string GetName()//override default implemented method
        {
            return $"FintechCustomer Name:{Name}";
        }

        public FintechCustomer(string name) => Name = name;

    }

    public class NormalCustomer : ICustomer
    {
        public string Name { get; set; }
        public int OrderCount { get; set; }

        public string GetOrderCount()
        {
            return $"Normal customer order count:{OrderCount}";
        }

        public NormalCustomer(string name)
        {
            Name = name;
            OrderCount = 0;
        }
    }

코드는이 개 구현 클래스와 인터페이스 ICustomer FintechCustomer, NormalCustomer이 포함되어 있습니다. 참고로 몇 가지 포인트가 있습니다 :

  1. ICustomer 인터페이스는 GetName의 구체적인 구현을 제공합니다
  2. FintechCustomer GetName 클래스함으로써 GetName ICustomer을 포함, 자신의 구현을 제공합니다
  3. NormalCustomer 클래스가 자신의 GetName이 달성 제공하지 않지만, GetName ICustomer 상속 재산은 다음의 예를 통해 호출이 없다, 우리는이 점을 확인할 수 있습니다
  4. ICustomer 인터페이스 내부, 회원 등 다양한 수정을 추가 할 수 있습니다 등 개인 보호, 공공,하지만 그들은 상속되지 않습니다.

코드는 다음과 같이 예입니다 호출

    public class DefaultInterfaceImplementationUnitTest
    {
        [TestMethod]
        public void FintechCustomer_TestGetName()
        {
            var name = "FintechCustomer1";
            var fc = new FintechCustomer(name);
            ICustomer ic = fc;
            Assert.AreEqual($"FintechCustomer Name:{name}", fc.GetName());
            Assert.AreEqual($"FintechCustomer Name:{name}", ic.GetName());
        }

        [TestMethod]
        public void NormalCustomer_TestGetName()
        {
            var name = "NormalCustomer1";
            var nc = new NormalCustomer(name);
            ICustomer ic = nc;
            //Assert.AreEqual(name, nc.GetName());//编译错误: Error CS1061  'NormalCustomer' does not contain a definition for 'GetName'...
            Assert.AreEqual(name, ic.GetName());
        }
    }

NormalCustomer_TestGetName 기능에서, 라인은 GetName 기능을 구현 ICustomer 인터페이스를 호출 할 수있는 구현 클래스 NormalCustomer 참조를 보여준다 주석, 단지 GetName ICustomer 참조에 의해 호출 될 수있다. 그러나 FintechCustomer_TestGetName, 우리는 볼 수 있는지 FintechCustomer의 기준은 ICustomer GetName 함수를 호출 할 수 있으며 FintechCustomer의 함수 호출이다.

더 많은 패턴 매칭

C # 7.0 소개하는 형식과, C # 8.0의 확장 된 사용을 일정하게하고 정합 스위치이다. 이러한 속성은 주로 지원 데이터에 대한 함수입니다 패러다임 프로그래밍 분리하고 데이터가 별도의 기능 또는 알고리즘 인 경우, 런타임 객체의 유형에 따라 이러한 속성을 사용하는 것을 고려하지 않는, 그들은의 표현의 대안 설계를 제공 방법. 우리는 스위치의 발현과 재산, 튜플, postition 세 가지 패턴 매칭 아래에 언급 될 것입니다.

스위치 식 (스위치 식)

예를 들어 봐

        public static RGBColor FromRainbow(Rainbow colorBand) =>
            colorBand switch
            {
                Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00),
                Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
                Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
                Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00),
                Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF),
                Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
                Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
                _ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
            };

        public enum Rainbow
        {
            Red,
            Orange,
            Yellow,
            Green,
            Blue,
            Indigo,
            Violet
        }

FromRainbow 위의 예에서, 우리는 주로 다음과 같은 네 가지 점에서, switch 문에 비해 스위치의 발현이 큰 변화를 겪은 것을 볼 수 있습니다 :

  1. 컴파일러가 쉽게 문 및 스위치 식을 전환 할 수 있다는 변수 이름 스위치 키워드의 전면에 (colorBand).
  2. => 치환하는 경우, 하나의 단부 각각 사용되지 않고, 그래서 더 간단하고 직관적 인 것이다.
  3. _ 기본 분기가 대체됩니다.
  4. 코드 조각 표현보다는 문입니다.

전화 케이스 일치하지 않는 경우 마지막으로, 스위치 표현, 값을 반환하거나 예외를 슬로우 할 필요가, 예외가 InvalidOperation을 발생합니다, 경고가 주어 졌을 때 모든 경우를 포함하지 않는 지점을 전환합니다 컴파일러.

속성 패턴 (대지 패턴)

다음 예에서 이야기입니다

       public static decimal ComputeSalesTax(Address location, decimal salePrice) =>
            location switch
            {
                { State: "WA" } => salePrice * 0.06M,
                { State: "MN" } => salePrice * 0.75M,
                { State: "MI" } => salePrice * 0.05M,
                // other cases removed for brevity...
                _ => 0M
            };

        public class Address
        {
            public string State { get; set; }
        }

상기 코드는 스위치 식의 내부와 일치하는 스위치 기능 ComputeSalesTax 식을 사용하여 특성의 패턴을 사용한다. 다음은 예를 나타냅니다 : "WA"의 주 속성 값의 위치, 그것은 salePrice * 0.06M을 반환하는 경우 :

 { State: "WA" } => salePrice * 0.06M,

튜플 패턴 (튜플 패턴)

어떤 알고리즘은 복수의 입력을 필요로 모델 식의 복수의 값과 일치하는 데 사용되는 스위치의 튜플 튜플은 다음은 예이다있게 :

    public static string RockPaperScissors(string first, string second)
    => (first, second) switch
    {
        ("rock", "paper") => "rock is covered by paper. Paper wins.",
        ("rock", "scissors") => "rock breaks scissors. Rock wins.",
        ("paper", "rock") => "paper covers rock. Paper wins.",
        ("paper", "scissors") => "paper is cut by scissors. Scissors wins.",
        ("scissors", "rock") => "scissors is broken by rock. Rock wins.",
        ("scissors", "paper") => "scissors cuts paper. Scissors wins.",
        (_, _) => "tie"
    };

상기는 스위치 식도 만이 (상기 해당 메시지가 반환된다 매칭 튜플하여 알 수있는 암석 종이 위 게임 , ) => "TIE"가 일치를 나타내는 없다 "타이"복귀 발견된다.

위치 모드 (위! 패턴)

클래스 Deconstrut 함수가 있다면 C # 7.0 소개 해체 기능은 직접적 변수 클래스의 상이한 특성들로 분해 될 수있다. C #에서 8.0 위치 스위치 발현 패턴에 의해 복수의 속성에 매칭 될 수 있으며, 다음은 예이다 :

        public static Quadrant GetQuadrant(Point point) => point switch
        {
            (0, 0) => Quadrant.Origin,
            var (x, y) when x > 0 && y > 0 => Quadrant.One,
            var (x, y) when x < 0 && y > 0 => Quadrant.Two,
            var (x, y) when x < 0 && y < 0 => Quadrant.Three,
            var (x, y) when x > 0 && y < 0 => Quadrant.Four,
            var (_, _) => Quadrant.OnBorder,
            _ => Quadrant.Unknown
        };

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

            public Point(int x, int y) => (X, Y) = (x, y);

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

그것은 별개로 분해 변수 X, Y를 할 수 있도록 본 실시 예에서, 포인트 클래스는 해체 기능을 포함한다. 분기 조건이 성립하는지 여부를 판단 할 때 GetQuadrant 함수, 오브젝트가 해체 두 변수 함수에 의해 포인트 X, Y로 분리하고있다.

문을 사용하여

이전 버전에서는, 우리는 수명주기의 끝에서는 IDisposable 개체의 실현을 보장하기 위해 사용하는 문을 사용할 수 있습니다, 그 폐기 방법이라고합니다. C # 8.0에서 우리는보다 컴팩트 한 문 및 코드를 사용하여 같은 일을. 여기에 열려있는 파일의 예입니다 :

static int WriteLinesToFile(IEnumerable<string> lines)
{
    using var file = new System.IO.StreamWriter("WriteLines2.txt");
    // Notice how we declare skippedLines after the using statement.
    int skippedLines = 0;
    foreach (string line in lines)
    {
        if (!line.Contains("Second"))
        {
            file.WriteLine(line);
        }
        else
        {
            skippedLines++;
        }
    }
    // Notice how skippedLines is in scope here.
    return skippedLines;
    // file is disposed here
}

위의 예에서, 함수 호출이 반환 할 때 파일 객체는 자동으로 폐기 방법은, 선언 된 객체를 사용하여는 IDisposable을 구현하지 않는 경우, 컴파일러는 오류 메시지를 생성 호출합니다.

정적 로컬 기능 (정적 지역 기능)

당신이 그 지역 변수 외부 캡처 로컬 기능을 방문하지 않으려면, 우리는 정적 제한을 추가 할 수 있습니다, 다음은 예입니다 :

        public int Add(int x, int y)
        {
            return x + y;

            int GetX()
            {
                return x;
            }

            static int GetY()
            {
                return y;//Compiler error:A static local function cannot contain a reference to 'y'
            }
        }

위의 예에서 추가 기능 GetY 정적 인 두 로컬 기능을 포함하지만, 로컬 변수 주연 Y를 의미하므로 컴파일 오류의 주석이있을 것이다.

일회용 심판 구조체

심판의 구조는 처분의 수 없도록는 IDisposable가 아니라 작업을 수행 물론 어떤 인터페이스를 구현하지 않기 때문에. C # 8.0, 오랫동안이 접근 공극 폐기 () 함수를 갖는 한, 그것은 폐기 될 수 있으며, 예는 다음이다 :

    ref struct DisposableRefStruct
    {
        public void Dispose()
        {
            Console.WriteLine("ref struct dispose method is called");
        }
    }

    public class DisposableRefStructTester
    {
        public static void Test()
        {
            using (var s = new DisposableRefStruct())
            {
                Console.WriteLine("Test Disposable Ref Struct");
            }
        }

는 IDisposable 인터페이스를 구현하지만, 무효 처분 () 메소드가 아닌 예를 들어 DisposableRefStruct에서 볼 수 있듯이, 그것은 단어와 문장을 사용하는 것도 가능합니다. 이 기능은 사용할 수 읽기 전용 심판 구조체입니다

널 (null) 참조 유형이 될 수 있습니다 (null 허용 기준 유형)

Null 참조 유형을 확인할 수 있습니다 프로젝트 파일에 다음과 같은 구성을 추가하여 켤 수 있습니다. 개봉 후, 컴파일러는 널 (null)이 유형을 더한 후, 이전과 동일 입력해야합니다, 모든 참조 형은 널 값을 할당되지 않은 생각합니까? 표현에 대한 참조 유형은 비어있을 수 있습니다. 자세한 내용은 참조하십시오
https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references
https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/nullable-reference- 유형
https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/upgrade-to-nullable-references를

<Nullable>enable</Nullable>

비동기 흐름 (비동기 스트림)

동기화에 대응하는 기능을 IEnumerable 비동기 버전은 비동기 스트림 기능은 다음과 같은 세 가지 기능을 가지고 있습니다 :

  1. 사용 비동기 수정
  2. 반환 유형은 다음과 같습니다 IAsyncEnumerable
  3. 기능 수율 반환 열거 패러다임을 구현하기 위해 문을 포함
    다음은 예입니다 :
        public static async IAsyncEnumerable<int> GenerateSequence()
        {
            for (int i = 0; i < 20; i++)
            {
                await Task.Delay(100);
                yield return i;
            }
        }

        public static async Task ConsumeAsyncStream()
        {
            await foreach (var i in GenerateSequence())
            {
                Console.WriteLine(i);
            }
        }

반환 실시 GenerateSequence ConsumeAsyncStream 비동기 스트림은 앞의 foreach AWAIT을 추가하여 비동기 스트림을 열거한다.

지수와 범위 (지수 및 범위)

그리고, 인덱스 범위는 단일 요소에 액세스하거나 시퀀스의 범위는 간단한 문법을 ​​제공한다. 파이썬의 조각,하지만 같은 문법이 개념 a를 비트는 약간 다릅니다. 구현이 함수는 다음과 같은 두 가지 새로운 유형과 두 개의 새로운 사업자에 따라 달라집니다

  1. System.Index는 시퀀스 인덱스를 나타낸다
  2. ^ 연산자는 인덱스가 뒤쪽에서 시작되는 의미
  3. System.Range는의 서브 시퀀스를 나타낸다
  4. ... 연산자의 범위의 시작과 끝을 나타내는

    다음과 같이 몇 가지 코드 예제는 다음과 같습니다

public class IndicesAndRanges
    {
        public string[] words = new string[]
                               {
                                            // index from start      index from end
                                "The",      // 0                     ^9
                                "quick",    // 1                     ^8
                                "brown",    // 2                     ^7
                                "fox",      // 3                     ^6
                                "jumped",   // 4                     ^5
                                "over",     // 5                     ^4
                                "the",      // 6                     ^3
                                "lazy",     // 7                     ^2
                                "dog"       // 8                     ^1
                               };           // 9 (or words.Length)   ^0

        public void Test()
        {
            Console.WriteLine($"The last word is {words[^1]}"); // writes "dog"
            var quickBrownFox = words[1..4];// "quick", "brown", and "fox"
            var lazyDog = words[^2..^0];//"lazy" and "dog"

            var allWords = words[..]; // contains "The" through "dog".
            var firstPhrase = words[..4]; // contains "The" through "fox"
            var lastPhrase = words[6..]; // contains "the", "lazy" and "dog"


            Range phrase = 1..4;//Range phrase = 1..4;
            var text = words[phrase];
        }
    }

널 합병 할당

C # 8.0 소개 널 = ?? 조합 할당 연산자. 왼쪽 피연산자가 null 때만 오른쪽 피연산자 값은 왼쪽 피연산자에 할당. 다음 예는 다음과 같다 :

List<int> numbers = null;
int? i = null;

numbers ??= new List<int>();
numbers.Add(i ??= 17);
numbers.Add(i ??= 20);

Console.WriteLine(string.Join(" ", numbers));  // output: 17 17
Console.WriteLine(i);  // output: 17

관리되지 않는 구성 유형

이전 타입 (파라미터 중 적어도 한 종류를 포함하는 타입)의 구성은, 단독 타입 할 수 없다. 만 단독 타입 필드를 포함하는 구조의 타입의 값이, 종류가 관리하지 않는 경우, 다음의 예는, 상기 C # 8.0의 시작 :

public struct Coords<T>
{
    public T X;
    public T Y;
}

이것은 관리되지 않는 다른 유형은 생성 될 수 있거나 형 스택에 할당 된 메모리 블록에 대한 포인터.

중첩 된 표현 stackalloc

C # 8.0 상기 식의 결과는 입력 된 stackalloc System.Span이면 또는 System.ReadOnlySpan 표현식 stackalloc 다른 표현에 사용할 수 있습니다, 다음은 구체적인 예는 다음과 같습니다

Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6 ,8 });
Console.WriteLine(ind);  // output: 1

문자열 보간 인핸스

"..."@ $와 $ @ "..."정확하지만 C #을 이전 버전의 $ 표시는 @ 기호 앞에 나타나야합니다 : $의 마크 @ 순서대로 문자열 보간 어디서나 배치 할 수 있습니다 .


FINTECH 괴짜

추천

출처www.cnblogs.com/dereklovecc/p/12393155.html