마이크로 채널 대중 번호 : 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이 포함되어 있습니다. 참고로 몇 가지 포인트가 있습니다 :
- ICustomer 인터페이스는 GetName의 구체적인 구현을 제공합니다
- FintechCustomer GetName 클래스함으로써 GetName ICustomer을 포함, 자신의 구현을 제공합니다
- NormalCustomer 클래스가 자신의 GetName이 달성 제공하지 않지만, GetName ICustomer 상속 재산은 다음의 예를 통해 호출이 없다, 우리는이 점을 확인할 수 있습니다
- 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 문에 비해 스위치의 발현이 큰 변화를 겪은 것을 볼 수 있습니다 :
- 컴파일러가 쉽게 문 및 스위치 식을 전환 할 수 있다는 변수 이름 스위치 키워드의 전면에 (colorBand).
- => 치환하는 경우, 하나의 단부 각각 사용되지 않고, 그래서 더 간단하고 직관적 인 것이다.
- _ 기본 분기가 대체됩니다.
- 코드 조각 표현보다는 문입니다.
전화 케이스 일치하지 않는 경우 마지막으로, 스위치 표현, 값을 반환하거나 예외를 슬로우 할 필요가, 예외가 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
비동기 버전은 비동기 스트림 기능은 다음과 같은 세 가지 기능을 가지고 있습니다 :
- 사용 비동기 수정
- 반환 유형은 다음과 같습니다 IAsyncEnumerable
- 기능 수율 반환 열거 패러다임을 구현하기 위해 문을 포함
다음은 예입니다 :
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를 비트는 약간 다릅니다. 구현이 함수는 다음과 같은 두 가지 새로운 유형과 두 개의 새로운 사업자에 따라 달라집니다
- System.Index는 시퀀스 인덱스를 나타낸다
- ^ 연산자는 인덱스가 뒤쪽에서 시작되는 의미
- System.Range는의 서브 시퀀스를 나타낸다
... 연산자의 범위의 시작과 끝을 나타내는
다음과 같이 몇 가지 코드 예제는 다음과 같습니다
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 #을 이전 버전의 $ 표시는 @ 기호 앞에 나타나야합니다 : $의 마크 @ 순서대로 문자열 보간 어디서나 배치 할 수 있습니다 .