What is new in C# 7,8,9,10

目录

What's new in C# 7

C# 7 in Visual Studio 2017

Out Variables

Pattern Matching

Tuples (System.ValueTuple)

 Deconstruct解构

Local Functions

Ref Returns and Locals

Expression Bodied Members

Throw Expressions

Generated Async Return Types

Literal Improvements

C# 7.1 in Visual Studio 2017.3

Compilation Issues (how to switch to C#7.1)

Async Main

Default Expressions

Ref Assemblies

Infer Tuple Names

Pattern-Matching with Generics

C# 7.2 in Visual Studio 2017 15.5

Leading Digit Separators

'Private Protected' Access Modifier

Non-Trailing Named Arguments

Reference Semantics on Value Types值类型的引用语义

C# 7.3 in Visual Studio 2017 15.5

Performance Improvement

Features Enhancements

Extensioned expression variables in initializers

New Compiler Features

What's new in C# 8

Nullable Reference Types

Method 1: 通过引用ReSharper.Annotations

Method 2: 通过使用string?

Override Null Checks

Diable nullable check

Enable nullable check

Index and Range

Default Interface Members

Extension to create Default function in Interface

Default function in iterface

Pattern Matching

What's new in C# 9 (. NET 5)

Record Types

浅拷贝with

Top-level Calls

Initial Setters

Pttern Matching Improvement

Target-Typed New

Source Generators

Partial Method Syntax and Modules Initializers(部分方法语法和模块初始化器)

What's new in C# 10 (. NET 6)

Record Structs

Global Using Directives

File-Scoped Namespace Declarations

Extended Property Patterns

Generic Attributes通用属性

Lambda Improvements,提高很多

Enhanced #line directives



What's new in C# 7

C# 7 in Visual Studio 2017

Out Variables

using System;
using static System.Console;namespace CSharp7Demos
{class OutVariables{static void MainOV(string[] args){DateTime dt; // structif (DateTime.TryParse("01/01/2017", out dt)){WriteLine($"Old-fashioned parse: {dt}");}// variable declaration is an expression, not a statementif (DateTime.TryParse("02/02/2016", out /*DateTime*/ var dt2)){WriteLine($"New parse: {dt2}");}// the scope of dt2 extends outside the if blockWriteLine($"I can use dt2 here: {dt2}");// what if the parse fails?int.TryParse("abc", out var i);WriteLine($"i = {i}"); // default value}}
}

Pattern Matching

using static System.Console;namespace CSharp7Demos
{public class Shape{}public class Rectangle : Shape{public int Width, Height;}public class Circle : Shape{public int Diameter;}public class PatternMatching{public void DisplayShape(Shape shape){if (shape is Rectangle){var rc = (Rectangle) shape;} else if (shape is Circle){// ...}var rect = shape as Rectangle;if (rect != null) // nonnull{//...}if (shape is Rectangle r){// use r}// can also do the invserseif (!(shape is Circle cc)){// not a circle!}switch (shape){case Circle c:// use cbreak;case Rectangle sq when (sq.Width == sq.Height):// square!break;case Rectangle rr:// use rrbreak;}var z = (23, 32);//switch (z)//{//  case (0, 0)://    WriteLine("origin");//}}static void Main(string[] args){}}
}

Tuples (System.ValueTuple)

using System;
using System.Linq;
using Microsoft.SqlServer.Server;
using static System.Console;namespace CSharp7Demos
{public class Point{public int X, Y;public void Deconstruct(out string s){s = $"{X}-{Y}";}public void Deconstruct(out int x, out int y){x = X;y = Y;}}public class Tuples{static Tuple<double, double> SumAndProduct(double a, double b){return Tuple.Create(a + b, a * b);}// requires ValueTuple nuget package// originally with no namesstatic (double sum, double product) NewSumAndProduct(double a, double b){return (a+b,a*b);}static void MainT(string[] args){// Newvar sp = SumAndProduct(2, 5);// sp.Item1 uglyWriteLine($"sum = {sp.Item1}, product = {sp.Item2}");var sp2 = NewSumAndProduct(2, 5);WriteLine($"new sum = {sp2.sum}, product = {sp2.product}");WriteLine($"Item1 = {sp2.Item1}");WriteLine(sp2.GetType());// converting to valuetuple loses all infovar vt = sp2;// back to Item1, Item2, etc...var item1 = vt.Item1; // :(// can use var below//(double sum, var product) = NewSumAndProduct(3, 5);var (sum, product) = NewSumAndProduct(3, 5);// note! var works but double doesn't// double (s, p) = NewSumAndProduct(3, 4);(double s, double p) = NewSumAndProduct(3, 4);//This can workWriteLine($"sum = {sum}, product = {product}");WriteLine(sum.GetType());// also assignmentdouble s, p;(s, p) = NewSumAndProduct(1, 10);// tuple declarations with names//var me = new {name = "Evan", age = 37}; // AnonymousTypevar me = (name: "Evan", age: 37);WriteLine(me);WriteLine(me.GetType());//Print is System.ValueTuple// names are not part of the type:WriteLine("Fields: " + string.Join(",", me.GetType().GetFields().Select(pr => pr.Name)));WriteLine("Properties: " + string.Join(",", me.GetType().GetProperties().Select(pr => pr.Name)));WriteLine($"My name is {me.name} and I am {me.age} years old");// proceed to show return: TupleElementNames in dotPeek (internally, Item1 etc. are used everywhere)// unfortunately, tuple names only propagate out of a function if they're in the signaturevar snp = new Func<double, double, (double sum, double product)>((a, b) => (sum: a + b, product: a * b));var result = snp(1, 2);// there's no result.sum unless you add it to signatureWriteLine($"sum = {result.sum}");}}
}

 Deconstruct解构

// deconstruction
Point pt = new Point {X = 2, Y = 3};
var (x,y) = pt; // interesting error here
Console.WriteLine($"Got a point x = {x}, y = {y}");// can also discard values
(int z, _) = pt;

Local Functions

CalculateDiscriminant可以放在方法SolveQuadratic体内,或者方法体外,放在方法体内是,所在的位置可以在调用前或者调用后面。

建议放在前面,方便代码维护。

  public class Employee{public int Id { get; set; }public string FirstName { get; set; }public string LastName { get; set; }public string MiddleName { get; set; }//normal ctor//public Employee(string firstName, string lastName, string middleName)//{//    FirstName = firstName;//    LastName = lastName;//    MiddleName = middleName;//}//lambda ctorpublic Employee(string firstName, string lastName, string middleName) => (FirstName, LastName, MiddleName) = (firstName, lastName, middleName);}
using System;namespace CSharpDemos
{public class EquationSolver{//private Func<double, double, double, double> CalculateDiscriminant = (aa, bb, cc) => bb * bb - 4 * aa * cc;//Quadratic 二次方程public static Tuple<double, double> SolveQuadratic(double a, double b, double c){//var CalculateDiscriminant = new Func<double, double, double, double>((aa, bb, cc) => bb * bb - 4 * aa * cc);//double CalculateDiscriminant(double aa, double bb, double cc)//{//  return bb * bb - 4 * aa * cc;//}//double CalculateDiscriminant(double aa, double bb, double cc) => bb * bb - 4 * aa * cc;//double CalculateDiscriminant() => b * b - 4 * a * c;//var disc = CalculateDiscriminant(a, b, c);var disc = CalculateDiscriminant();var rootDisc = Math.Sqrt(disc);return Tuple.Create((-b + rootDisc) / (2 * a),(-b - rootDisc) / (2 * a));// can place heredouble CalculateDiscriminant() => b * b - 4 * a * c;}//private static double CalculateDiscriminant(double a, double b, double c)//{//  return b * b - 4 * a * c;//}}public class LocalFunctions{static void MainT(string[] args){var result = EquationSolver.SolveQuadratic(1, 10, 16);Console.WriteLine(result);}}
}

Ref Returns and Locals

using System;
using System.Collections.Generic;
using static System.Console;namespace CSharpDemos
{public class RefReturnsAndLocals{static ref int Find(int[] numbers, int value){for (int i = 0; i < numbers.Length; i++){if (numbers[i] == value)return ref numbers[i];}// cannot do by value return//return -1;// cannot return a local//int fail = -1;//return ref fail;throw new ArgumentException("meh");}static ref int Min(ref int x, ref int y){//return x < y ? (ref x) : (ref) y;//return ref (x < y ? x : y);if (x < y) return ref x;return ref y;}static void MainRRL(string[] args){// reference to a local elementint[] numbers = { 1, 2, 3 };ref int refToSecond = ref numbers[1];var valueOfSecond = refToSecond;// cannot rebind// refToSecond = ref numbers[0];refToSecond = 123;WriteLine(string.Join(",", numbers)); // 1, 123, 3// reference persists even after the array is resizedArray.Resize(ref numbers, 1);WriteLine($"second = {refToSecond}, array size is {numbers.Length}");refToSecond = 321;WriteLine($"second = {refToSecond}, array size is {numbers.Length}");//numbers.SetValue(321, 1); // will throw// won't work with listsvar numberList = new List<int> {1, 2, 3};//ref int second = ref numberList[1]; // property or indexer cannot be outint[] moreNumbers = {10, 20, 30};//ref int refToThirty = ref Find(moreNumbers, 30);//refToThirty = 1000;// disgusting use of languageFind(moreNumbers, 30) = 1000;WriteLine(string.Join(",",moreNumbers));// too many references:int a = 1, b = 2;ref var minRef = ref Min(ref a, ref b);// non-ref call just gets the valueint minValue = Min(ref a, ref b);WriteLine($"min is {minValue}");}}
}

Expression Bodied Members

using System.Collections.Generic;namespace CSharpDemos
{// community contributed featurepublic class Person{private int id;private static readonly Dictionary<int, string> names = new Dictionary<int, string>();public Person(int id, string name) => names.Add(id, name);~Person() => names.Remove(id);public string Name{get => names[id];set => names[id] = value;}}
}

Throw Expressions

using System;
using static System.Console;namespace CSharpDemos
{public class ThrowExpressions{public string Name { get; set; }public ThrowExpressions(string name){Name = name ?? throw new ArgumentNullException(paramName: nameof(name));}int GetValue(int n){return n > 0 ? n + 1 : throw new Exception();}static void MainTE(string[] args){int v = -1;try{var te = new ThrowExpressions("");v = te.GetValue(-1); // does not get defaulted!}catch (Exception e){Console.WriteLine(e);}finally{WriteLine(v);}}}
}

Generated Async Return Types

using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;namespace CSharpDemos
{public class GeneralizedAsyncReturnTypes{public static async Task<long> GetDirSize(string dir){if (!Directory.EnumerateFileSystemEntries(dir).Any())return 0;// Task<long> is return type so it still needs to be instantiatedreturn await Task.Run(() => Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories).Sum(f => new FileInfo(f).Length));}// C# 7 lets us define custom return types on async methods// main requirement is to implement GetAwaiter() method// ValueTask is a good example// need nuget packagepublic static async ValueTask<long> NewGetDirSize(string dir){if (!Directory.EnumerateFileSystemEntries(dir).Any())return 0;// Task<long> is return type so it still needs to be instantiatedreturn await Task.Run(() => Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories).Sum(f => new FileInfo(f).Length));}static void MainGART(string[] args){// async methods used to require void, Task or Task<T>// C# 7 allows other types such as ValueType<T> - prevent// allocation of a task when the result is already available// at the time of awaitingConsole.WriteLine(NewGetDirSize(@"c:\temp").Result);}}
}

Literal Improvements

namespace CSharpDemos
{public class LiteralImprovements{static void MainLI(string[] args){int a = 123_321;int b = 123_321______123;// cannot do trailing//int c = 1_2_3___; // R# remove// also works for hexlong h = 0xAB_BC_D123EF;// also binayvar bin = 0b1110_0010_0011;}}
}

C# 7.1 in Visual Studio 2017.3

Compilation Issues (how to switch to C#7.1)

 以下内码在vs2017.3中会报编译错误,你可以从Solution Explore右击Project-->Properties-->Build --> Advance去更改C#版本到7.1去解决编译错误。

static async Task Main(string[] args){Console.WriteLine("ABC");}

Async Main

using System;
using System.Net.Http;
using System.Threading.Tasks;namespace CSharpDemos
{internal class Program{// used to be the case that your demo// would have to reside in a separate// bodyprivate static string url = "http://google.com/robots.txt";//private static async Task MainAsync(string s)//{//  // blah//  Console.WriteLine(await new HttpClient().GetStringAsync(s));//}//public static void Main(string[] args)//{//  // fine//  MainAsync(url).GetAwaiter().GetResult();//}// there is no async void, it's// Task Main// Task<int> Main if you need to returnstatic async Task Main(string[] args){Console.WriteLine(await new HttpClient().GetStringAsync(url));}}
}

Default Expressions

using System;
using System.Collections.Generic;
using static System.Console;namespace CSharpDemos
{public class DefaultLiteral{// allowed in argument names// only upside: switching from ref to value type// VS Action 'Simplify Default Expression'public DateTime GetTimestamps(List<int> items = default(List<int>)){// ...return default;}/// <summary>/// Default literal, one of the slightly meaningless features./// </summary>static void Main(){// Simplify default expression hereint a = default(int);WriteLine(a);int av = default;//same as above, 0 is int default valueWriteLine(av);int b = default;WriteLine(b);// constants are ok if the inferred type is suitableconst int c = default;WriteLine(c);// will not work here// const int? d = default; // oops// cannot leave defaults on their ownvar e = new[] {default, 33, default};WriteLine(string.Join(",", e));// rather silly way of doing things; null is shorterstring s = default;WriteLine(s == null);// comparison with default is OK if type can be inferredif (s == default){WriteLine("Yes, s is default/null");}// ternary operationsvar x = a > 0 ? default : 1.5;WriteLine(x.GetType().Name);}}
}

Ref Assemblies

利用Refelection反编译后,代码实现部分只有null返回,其他部分被隐藏了。

Infer Tuple Names

using System;
using System.Linq;namespace CSharpDemos
{using static System.Console;public class InferTupleNames{// Tuple projection initializerspublic static void Main(string[] args){// reminder: tuplesvar me = (name: "Evan", age: 37);WriteLine(me);var alsoMe = (me.age, me.name);WriteLine(alsoMe.Item1); // typicalWriteLine(alsoMe.name); // newvar result = new[] {"March", "April", "May"} // explicit name not required.Select(m => (/*Length:*/ m/*?*/.Length, // optionally nullableFirstChar: m[0])) // some names (e.g., ToString) disallowed.Where(t => t.Length == 5); // note how .Length is available hereWriteLine(string.Join(",", result));// tuples produced by deconstructionvar now = DateTime.UtcNow;var u = (now.Hour, now.Minute);var v = ((u.Hour, u.Minute) = (11, 12));WriteLine(v.Minute);}}
}

Pattern-Matching with Generics

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace CSharpDemos
{using static System.Console;public class Animal{}public class Pig : Animal{}public class PatternMatchingWithGenerics{public static void Cook<T>(T animal)where T : Animal{// note the red squiggly!// cast is redundant hereif ((object)animal is Pig pig){// cook and eat itWrite("We cooked and ate the pig...");}switch (/*(object)*/animal){case Pig pork:WriteLine(" and it tastes delicious!");break;}}/// <summary>/// Need to fall back to C# 7 for this./// </summary>static void Main(string[] args){var pig = new Pig();Cook(pig);}}
}

C# 7.2 in Visual Studio 2017 15.5

Leading Digit Separators

  class LeadingUnderscoresNumericSeparators{static void Main(string[] args){// binaryvar x = 0b_1111_0000;// hexvar y = 0x_baad_f00d;}}

'Private Protected' Access Modifier

public class Base{private int a;protected internal int b; // derived classes or classes in same assemblyprivate protected int c;  // containing class or derived classes in same assembly only }class Derived : Base{public Derived(){c = 333; // fineb = 3; // no}}class Foo{static void Main(string[] args){Base pp = new Base();var d = new Derived();d.b = 3;// d.c is a no-go}}

Non-Trailing Named Arguments

static void doSomething(int foo, int bar){}static void Main(string[] args){doSomething(foo: 33, 44);// still illegal//doSomething(33, foo:44)}

Reference Semantics on Value Types值类型的引用语义

'In' Parameters

'Ref Readonly' Variables

'Ref Struct' and Span

struct Point{public double X, Y;public Point(double x, double y){X = x;Y = y;}public void Reset(){X = Y = 0;}// we don't want to recreate origin as new Point(), so...private static Point origin = new Point();public static ref readonly Point Origin => ref origin;public override string ToString(){return $"({X},{Y})";}}public class RefSemanticsValueTypes{// IN PARAMETERSvoid changeMe(ref Point p){p.X++;}// structs are passed by reference (i.e. address, so 32 or 64 bits)// 'in' is effectively by-ref and read-onlydouble MeasureDistance(in Point p1, in Point p2){// cannot assign to in parameter// p1 = new Point();// cannot pass as ref or out method// obvious// changeMe(ref p2);p2.Reset(); // instance operations happen on a copy!var dx = p1.X - p2.X;var dy = p1.Y - p2.Y;return Math.Sqrt(dx * dx + dy * dy);}// cannot create overloads that differ only in presence?// yeah you can, but//double MeasureDistance(Point p1, Point p2)//{//  return 0.0;//}public RefSemanticsValueTypes(){var p1 = new Point(1, 1);var p2 = new Point(4, 5);var distance = MeasureDistance(p1, p2);//             ^^^^ call ambiguousConsole.WriteLine($"Distance between {p1} and {p2} is {distance}");// can also pass in temporariesvar distFromOrigin = MeasureDistance(p1, new Point());var alsoDistanceFromOrigin = MeasureDistance(p2, Point.Origin);// REF READONLY RETURNS// make an ordinary by-value copyPoint copyOfOrigin = Point.Origin;// it's readonly, you cannot do a ref!//ref var messWithOrigin = ref Point.Origin;ref readonly var originRef = ref Point.Origin;// won't work//originRef.X = 123;}// REF STRUCTS// a value type that MUST be stack-allocated// can never be created on the heap// created specifically for Span<T>class CannotDoThis{Span<byte> stuff;}static void Main(string[] args){new RefSemanticsValueTypes();unsafe{// managedbyte* ptr = stackalloc byte[100];Span<byte> memory = new Span<byte>(ptr, 100);// unmanagedIntPtr unmanagedPtr = Marshal.AllocHGlobal(123);Span<byte> unmanagedMemory = new Span<byte>(unmanagedPtr.ToPointer(), 123);Marshal.FreeHGlobal(unmanagedPtr);}// implicit castchar[] stuff = "hello".ToCharArray();Span<char> arrayMemory = stuff;// string is immutable so we can make a readonly spanReadOnlySpan<char> more = "hi there!".AsSpan();Console.WriteLine($"Our span has {more.Length} elements");arrayMemory.Fill('x');Console.WriteLine(stuff);arrayMemory.Clear();Console.WriteLine(stuff);}}

C# 7.3 in Visual Studio 2017 15.5

Performance Improvement

    • Fixed-sized buffers
    • Ref local variables maybe reassigned
    • stackalloc arrays support initializers
    • int* pArr1=stackalloc int[3]{1,2,3}
      int* pArr2=stackalloc int[]{1,2,3}

Features Enhancements

  • Attributes on backing fields of auto-props (auto-props的后置字段上的属性)
[field:SomeCleverAttribute]
public float SomeProperty{get;set;}

Extensioned expression variables in initializers

public class B
{public B(int i,out int j){j=i;    }
}
public class D:B
{public D(int i):B(i,out var j){Console.WriteLine($"j = {j}}");  }
}
    • Tutple support == and !=
    • Imrpove overload resolution rules for method groups

New Compiler Features

    • --deterministic
    • --publicsign

What's new in C# 8

Nullable Reference Types

Method 1: 通过引用ReSharper.Annotations

[CanBeNull] Foo foo 会被解析为 Foo? foo

[CanBeNull] string middleName会被解析为string? middleName

   public class Employee{public int Id { get; set; }public string FirstName { get; set; }public string LastName { get; set; }[CanBeNull] public string MiddleName { get; set; }//CanBeNull is coming from ReSharper.Annotations on NuGetpublic Employee(string firstName, string lastName, [CanBeNull] string middleName) => (FirstName, LastName, MiddleName) = (firstName, lastName, middleName);public string FullName => $"{FirstName} {MiddleName} {LastName}";}

Method 2: 通过使用string?

    public class Employee{public int Id { get; set; }public string FirstName { get; set; }public string LastName { get; set; }public string? MiddleName { get; set; }//[CanBeNull] public string MiddleName { get; set; }//CanBeNull is coming from ReSharper.Annotations on NuGet//public Employee(string firstName, string lastName, [CanBeNull] string middleName) => (FirstName, LastName, MiddleName) = (firstName, lastName, middleName);public Employee(string firstName, string lastName, string? middleName) => (FirstName, LastName, MiddleName) = (firstName, lastName, middleName);public string FullName => $"{FirstName} {MiddleName} {LastName}";}

以下代码会提示一个Warning:MiddleName maybe null here. CS8602:Dereference  of a possible null reference.

public string FullName => $"{FirstName} {MiddleName[0]} {LastName}";

If nullability is enabled 

string? ≠ Nullable<string>

string? is still a string, but we need null checks.

public string FullName => $"{FirstName} {MiddleName?[0]} {LastName}";
        void Test(){string? str = GetString();//Will get warning belowchar c = str[0];//no warningif (str != null){char c2 = str[0];}}
Override Null Checks

2 ways to stop null checks

  • 1. Keep the variable non-nullable
public string MiddleName { get; set; } = string.Empty;
  • 2. Write expression with a bang(!)
public string MiddleName { get; set; } = null!;  
//Warning(null as Employee).FullName//No Warning(null as Employee)!.FullName//No Warning. !可以随便输入多少个,都是合法的(null as Employee)!!!!!!!!!.FullName
Diable nullable check

Edit **csproj file

 <Nullable>disable</Nullable>
Enable nullable check

Edit **csproj file,it is default setting.

<Nullable>enable</Nullable>

Code in below are no warning. 

//No warning
Type t = Type.GetType(nameof(Employee));
string name = t.Name; //No warning
Type? t2 = Type.GetType(nameof(Employee));
string name = t2.Name; 

Index and Range

Points into an array

  • Value
  • IsFromEnd
    Index ids = 2;//implict conversionIndex idx2 = new Index(0, false);var idx3 = ^0;//Index (0, true)// -1 is not last
//Index
var items = new[] { 1, 2, 3, 4 };
items[^2] = 33;//^2 去倒数第二个数值
Console.WriteLine($"{string.Join(",", items)}");//1,2,33,4//Range from a[X...Y] means from a[X] to a[Y].
//If X > Y will through ArgumentOutOfRangeException
items = new[] { 1, 2, 3, 4 };
var items2 = items[0..2];//从第一个开始取值,总共取两个值
Console.WriteLine($"{string.Join(",", items2)}");//1,2//Index + Range
var items3 = items[0..^0];//从第一个开始取值,取到最后一个值
Console.WriteLine($"{string.Join(",", items3)}");//1,2,3,4//Array slices yield copies
var test = items[..2];//Create a copy
Console.WriteLine($"{string.Join(",", test)}");//1,2
var test2 = items.AsSpan<int>();//{1,2,3,4}
Console.WriteLine("Span");
foreach (var item in test2)
{Console.WriteLine($"{item}");
}

Default Interface Members

Extension to create Default function in Interface

    public interface IHuman{string Name { get; set; }}public static class HumanExtension{public static void SayHello(this IHuman human){Console.WriteLine($"Hello, I am {human.Name}");}}

Default function in iterface

It is same behavior with above code.

    public interface IHuman{string Name { get; set; }public void SayHello(){Console.WriteLine($"Hello, I am {Name}");}}

Call demo:

//Human human2 = new Human("Alex");
//human2.SayHello();//Compiler errorIHuman human = new Human("Alex");
human.SayHello();//Hello, I am Alex((IHuman)new Human("Alex")).SayHello();//Hello, I am Alex

 Interface override

    public class IFrieldlyHuman : IHuman//IHuman is same with code in above{public string Name { get; set; }public void SayHello(){Console.WriteLine($"Greeting, I am {Name}");}}public class Human2 : IFrieldlyHuman{public Human2(string name){Name = name;}}//call demo
((IFrieldlyHuman)new Human2("Alex")).SayHello();//Greeting, I am Alex

Pattern Matching

哪个人设计的这个绕的写法。。。

    struct PhoneNumer{public int Code, Number;}private void TestPhone(){var phoneNumer = new PhoneNumer();string? origin;//哪个人设计的这种写法,难读的要命origin = phoneNumer switch{{ Number: 110 } => "Police",{ Code: 86 } => "China",{ } => null};//个人还是喜欢下面的写法switch (phoneNumer){case { Number: 110 }:origin = "Police";break;case { Code: 86 }:origin = "China";break;default:origin = null;break;}}

What's new in C# 9 (. NET 5)

Record Types


var p = new Person() { Name = "Evan", Age = 37 };
var p2 = new Person() { Name = "Evan", Age = 37 };
Console.WriteLine(p);//Print: Person { Name = Evan, Age = 37, Address =  }
Console.WriteLine(p2);//Print: Person { Name = Evan, Age = 37, Address =  }
Console.WriteLine($"p==p2? {p == p2}");//Print: p==p2? truevar address = new Address() { AreaCode = 123456, Stress = "星火北路8号" };
var address2 = new Address() { AreaCode = 123456, Stress = "药谷大道8号" };
Console.WriteLine($"address==address2? {address == address2}");//Print: address==address2? falsep.Address = address;
p2.Address = address;
Console.WriteLine($"p==p2? {p == p2}");//Print: p==p2? true
p2.Address = address2;
Console.WriteLine($"p==p2? {p == p2}");//Print: p==p2? falsepublic record Person
{public string Name { get; set; }public int Age { get; set; }public Address Address { get; set; }
}public class Address
{public int AreaCode { get; set; }public string Stress { get; set; }
}

浅拷贝with

Car car = new() { Engine = "V6", Color = new CarColor() { Name = "Black", Metallic = false } };
Car upgradeCar = car with { Engine = "V8" };//Clone()=shallow copy. 浅拷贝
upgradeCar.Color.Metallic = true;
Console.WriteLine(car);//Print: Car { Engine = V6, Color = CarColor { Name = Black, Metallic = True } }
Console.WriteLine(upgradeCar);//Print: Car { Engine = V8, Color = CarColor { Name = Black, Metallic = True } }
public record Car
{public string Engine { get; set; }public CarColor Color { get; set; }
}
public record CarColor
{public string Name { get; set; }public bool Metallic { get; set; }
}

Top-level Calls

Program.cs 没有namespace了。


Console.WriteLine("Hello, World!");Foo();void Foo()
{Console.WriteLine("Hello, Foo!");
}

Initial Setters

    public class Demo{//readonly filed only can set value in initial or in ctorpublic readonly string Filed = "ABC";public Demo(string filed){Filed = filed;}}
    public class Demo{//Inital only can set value in the class it ctor, not by call or functionpublic int Age { get; init; }public Demo(int filed){Age = filed;}//Below code will get errorpublic void ChangeValue(int newValue){Age = newValue;}}public class CallDemo{void Main(){//Below code will get errorvar p = new Demo() { Age = 37 };}}

Pttern Matching Improvement

object obj;
if (obj is not null)
{}
if (obj is not string)//same as !(obj is string)
{}int temperature = 40;
var feel = temperature switch
{< 0 => "冷",>= 0 and < 20 => "温暖",>= 20 and not 40 => "热",40 or 666 => "热死了"
};
Console.WriteLine(feel);public static bool IsLetter(this char c) =>c is >= 'a' and <= 'z' or >= 'A' and <= 'Z';public static bool IsLetterOrSeparator(this char c) =>c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or ';' or ',';

Target-Typed New

Person p=new Person();var p2=new Person();Person p=new();

Source Generators

Microsoft.CodeAnalysis.Analyzers, NugGet, ISourceGenerator

T4

using Microsoft.CodeAnalysis;
namespace Gen
{[Generator]public class Generator : ISourceGenerator{public void Execute(GeneratorExecutionContext context){var source=@"class Foo{public string Bar=""bar"";}";context.AddSource("Gen.cs",source)}public void Execute(GeneratorInitializationContext context){}}
}//更改.csproj <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles><CompilerGeneratedFilesOutputPath>c:\temp</CompilerGeneratedFilesOutputPath>//Build 完成后,在c:\temp\Gen\GenGenerator 会生成一个Gen.cs文件

Partial Method Syntax and Modules Initializers(部分方法语法和模块初始化器)

Startup.cs in API

What's new in C# 10 (. NET 6)

Visual Studio go to x64.

Record Structs

Same as Record class, but value types

Synthesuized members合成的成员

  •         Constructure,Deconstructure,Equals/==/!=, GetHashCode, PrintMembers, ToString

Predictable differences to record classes

  • Eg: Equals() does not do null check

Performance can be significantly better than ordinary structs

  • Also better than value Tuple
  • Default Equals()/GetHaskCode() implementations are bad (boxing etc.)
  • Record struct can be 20x faster with 100% less allocations

Restrictions

  • Cannot have a clone member
  • Instance field cannot be unsafe
  • annot declare a destructor
//small, composite value types
record struct Point<T>(T x, T y){...}
Point<int> p=new (100,200);//Record structs are mutable(可变的)
//Mutable structs are dangerous
player.Position.X++;// does nothing. means don't change anything//Recommend:
record struct Point2<T>(T x, T y){...}
p.X++;//will not compile

Global Using Directives

using System has been replaced because we have global using System.

我们可以创建一个GlobalUsings.cs,把常用的引用放在里面。

.NET6 project included several global usings that are implicit(隐式的):

<ImplicitUsings>enable</ImplicitUsings>

File-Scoped Namespace Declarations

vs有工具去选择“”Tofile-scoped namespace“”

Extended Property Patterns

static void Test()
{object obj;//Check properties using dot notationif (obj is Developer { Manager.FirstName: "Sam" } d){Console.WriteLine(d.Manager.FirstName);}//Check multiple patterns and arbitrary(任意的) depthif (obj is Developer { Manager.FirstName.Length: 5, Manager.yearOfWork: 10 } d2){Console.WriteLine(d2.Manager.FirstName);}
}public class Developer
{public string FirstName { get; set; }public string LastName { get; set; }public Manager Manager { get; set; }
}public class Manager
{public string FirstName { get; set; }public string LastName { get; set; }public int yearOfWork { get; set; }
}

Generic Attributes通用属性

//Current approacgh to taking a type in an attribute
class MyAttribute: Attribute
{MyAttribute(Type type){...}//伪代码
}
//usege 
[My(typeof(Foo))]//Now we can use type parameters instead:
class My Attribute
{...
}
//usege 
[My<float>] public void Bar(){...}//Type parameters from containing type cannot be used in attributes.eg:
public class Program<T>
{[SomeAttr<T>] void Foo(){...}//got error[SomeAttr<List<T>>] void Foo(){...}//got error
}

Lambda Improvements,提高很多

//Add attributes to lambda
var f=[A]{}=>{...};
//Demo:
var f=[return:A] x=>x;//syntax error at '=>', wrong demo
var f=[return:A] (x)=>x;//[A] lambda. Correct demo//Multiple attributes
var f=[a1,a2][a3]()=>{};
var f2=([a1][a2,a3] int x)=>x;//Attributes not support in delegate. will get error in below code:
f=[a] delegate {return 1;}// syntax error at 'delegate'
f=delegate ([a] int x) {return 1;}// syntax error at '['//Collection initializers also use [a] syntax,so, the parser will differences:
var f=new C {[A]=x};//means: f[A]=x
var f2=new C {[A] x=>x};//means: f2[0]=[A] x=>x//? (conditional element), cannot go in front:
x=b? [A];// correct
y=b? [A] ()=>{}:z;//error, syntax error at '('//Explict return type
//You can specify an explicit return type before the parameters
f=T()=>{};//correct
f= ref int (ref int x) => ref x;//correct
f=static void (_) => {};//correct//Not support delegate{} syntax
f= delegate int {retur 1;};// syntax error
f= delegate int (int x) {return x;};//syntax error//Exact method type inference from lambda return:
static void F<T> (Func<T,T> f) {...}
F(int (i) => i);//Func<int,int>//Varaibles conversion not allowed from lambda return type to delegate return type:
Func<object> f = string ()=> 'Evan';//error
Func<object?> f2 = object()=>x; //Warning//Lambda expressions with ref return types are allowed within expressions (without additional parens圆括号)
d= ref int () =>x;// equals: d=(ref int () => x)
F(ref int() => x);// equals: F((ref int() => x))//Var cannot be used as explicit return type
d=var (var x)=>x;//Error: contextula keyword 'var' cannot be used as explicit lambda return type//Lambda will be infered to Action/Func<>
var f =()=>1;// System.Func<int>
var f2 = string() => "Evan";// System.Func<string>
var f3 = delegate (object o) (object o) {};// System.Action<object>

Enhanced #line directives

debug/diagnostics/if**

#if ANYCPU
...
#endif#if DEBUG
...
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/426438.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

02 基于STM32的按键控制继电器驱动电机

本专栏所有源资料都免费获取&#xff0c;没有任何隐形消费。 注意事项&#xff1a;STM32仿真会存在各种各样BUG&#xff0c;且尽量按照同样仿真版本使用。本专栏所有的仿真都采用PROTEUS8.15。 本文已经配置好STM32F103C8T6系列&#xff0c;在PROTUES仿真里&#xff0c;32单片…

Games101图形学笔记——着色

Shading Z-buffering&#xff08;深度缓冲&#xff09; Shading&#xff08;着色&#xff09;画家算法Z-BufferShading(着色&#xff09;Blinn-Phong Reflectance Model&#xff08;布林冯反射模型&#xff09;漫反射能量守恒 着色高光Blinn-Phong Reflection ModelShadingFreq…

webGL 综合教程100+【目录】

webGL 综合教程100旨在为开发者提供两大方面的知识信息&#xff1a;&#xff08;1&#xff09;提供详细的每个api知识点的详解 &#xff08;2&#xff09;提供实战的示例&#xff0c;提供源代码。 在这量大系统性的知识下&#xff0c;给用户提供清晰的思路和示例参考&#xff0…

IEEE-754 32位十六进制数 转换为十进制浮点数

要将 IEEE-754 32位十六进制数 转换为 十进制浮点数&#xff0c;可以使用LabVIEW中的 Type Cast 函数。以下是一些具体步骤&#xff0c;以及相关实例的整理&#xff1a; 实现步骤&#xff1a; 输入十六进制数&#xff1a;在LabVIEW中&#xff0c;首先需要创建一个输入控制器&am…

传输层协议——udp/tcp

目录 再谈端口号 udp 协议 理解报头 udp特点 缓冲区 udp使用的注意事项 tcp协议 TCP的可靠性与提高效率的策略 序号/确认序号 窗口大小 ACK&#xff1a; PSH URG RST 保活机制 重传 三次握手(SYN) 四次挥手(FIN) 流量控制 滑动窗口 拥塞控制 延迟应答 捎带应答 面…

GPT撰写开题报告教程——课题确定及文献调研

撰写开题报告是一项复杂而重要的任务&#xff0c;需要涵盖从主题选择到文献综述、研究方法等多个环节。借助AI&#xff0c;如ChatGPT&#xff0c;可以显著提高这一过程的效率以及内容的质量。本文将详细探讨如何一步步利用ChatGPT撰写开题报告。 一、开题报告内容 一个清晰的…

[数据集][目标检测]智慧养殖场肉鸡健康状态检测数据集VOC+YOLO格式4657张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;4657 标注数量(xml文件个数)&#xff1a;4657 标注数量(txt文件个数)&#xff1a;4657 标注…

基于SpringBoot的社区宠物管理与推荐系统的设计与实现

文未可获取一份本项目的java源码和数据库参考。 1.课题的基本内容&#xff0c;可能遇到的困难&#xff0c;提出解决问题的方法和措施 2.1课题的基本内容 本课题主要研究基于SpringBoot的社区宠物管理与推荐系统的设计与实现。用户注册登录系统前端后可以可以实现对宠物信息的…

保护您的隐私:隐藏 IP 地址的重要性

在当今的数字时代&#xff0c;我们的在线隐私和安全变得比以往任何时候都更加重要。浏览互联网时保护自己的一种方法是隐藏您的 IP 地址。 但是为什么要隐藏您的 IP 地址以及如何有效地做到这一点&#xff1f; 隐藏您的 IP 地址有助于保护您的在线匿名性。您的 IP 地址就像您的…

vscode技巧-eslint配置

开发环境 jsvue3axios 下载插件 Eslint、Prettfier 配置过程 1.配置eslint 进入settings&#xff0c;输入eslint&#xff0c;在settings.json中替换一下文件 // #每次保存的时候自动格式化 {"editor.codeActionsOnSave": {"source.fixAll.eslint": &…

低代码开发平台系统架构概述

概述 织信低代码开发平台&#xff08;产品全称&#xff1a;织信Informat&#xff09;是一款集成了应用设计、运行与管理的综合性平台。它提供了丰富的功能模块&#xff0c;帮助用户快速构建、部署和维护应用程序。织信低代码平台通过集成丰富的功能模块&#xff0c;为用户提供…

国产分布式数据库-tidb单机部署文档

tidb单机部署文档 1、创建用户 #创建用户 useradd tidb #设置密码 passwd tidb2、配置免密码登录 编辑/etc/sudoers文件,文末加入&#xff1a; tidb ALL(ALL) NOPASSWD:ALL如果想要控制某个用户(或某个组用户)只能执行root权限中的一部分命令, 或者允许某些用户使用sudo时…

游戏各个知识小点汇总

抗锯齿原理记录 SSAA&#xff1a;把成像的图片放大N倍&#xff0c;然后每N个点进行平均值计算。一般N为2的倍数。比如原始尺寸是1000x1000&#xff0c;长宽各放大2倍变成2000x2000。 举例&#xff1a; 原始尺寸&#xff1a; 放大2倍后 最后平均值计算成像&#xff1a; MSAA&…

[OpenCV] 数字图像处理 C++ 学习——14霍夫变换直线、圆检测 附完整代码

文章目录 前言1.霍夫变换原理(1)霍夫变换检测直线的原理(2)霍夫变换检测圆的原理 2.代码实现(1)霍夫直线检测(2)霍夫圆检测 3.完整代码 前言 霍夫变换是一种有效的检测图像中的几何形状&#xff08;如直线、圆等&#xff09;的算法。霍夫变换通过将几何形状的检测问题转化为参…

python学习第十节:爬虫基于requests库的方法

python学习第十节&#xff1a;爬虫基于requests库的方法 requests模块的作用&#xff1a; 发送http请求&#xff0c;获取响应数据&#xff0c;requests 库是一个原生的 HTTP 库&#xff0c;比 urllib 库更为容易使用。requests 库发送原生的 HTTP 1.1 请求&#xff0c;无需手动…

引领智能家居新风尚,WTN6040F门铃解决方案——让家的呼唤更动听

在追求高效与便捷的智能家居时代&#xff0c;每一个细节都承载着我们对美好生活的向往。WTN6040F&#xff0c;作为一款专为现代家庭设计的低成本、高性能门铃解决方案&#xff0c;正以其独特的魅力&#xff0c;悄然改变着我们的居家生活体验。 芯片功能特点&#xff1a; 1.2.4…

关于订单信息的Excel数据分析报告

提升自己&#xff0c;掌握数据分析的能力&#xff0c;最快的方式就是实践&#xff01; 这里又是一个Excel数据分析项目的分析报告&#xff0c;有需要项目配套数据集的可以关注私信我免费获取(●◡●)

Skytower

一、安装配置靶机 下载地址: SkyTower: 1 ~ VulnHub 下载之后解压发现是VirtualBox格式的 我们下载一个VirtualBox&#xff0c;这是官网 Downloads – Oracle VirtualBox 安装到默认路径就 打开后点击注册 选择解压后的vbox文件 然后点击左上角管理 点击导出虚拟电脑&…

MUNIK谈ASPICE系列专题分享(十)ASPICE配置管理如何做

前言&#xff1a; ASPICE&#xff08;Automotive Software Process Improvement and Capability dEtermination&#xff09;是一种用于评估汽车行业软件开发过程成熟度的模型。配置管理是ASPICE中的一个关键过程领域&#xff08;KPA&#xff09;&#xff0c;它涉及到对软件项目…

【Linux篇】Http协议(1)(笔记)

目录 一、http基本认识 1. Web客户端和服务器 2. 资源 3. URI 4. URL 5. 事务 6. 方法 7. 状态码 二、HTTP报文 1. 报文的流动 &#xff08;1&#xff09;流入源端服务器 &#xff08;2&#xff09;向下游流动 2. 报文语法 三、TCP连接 1. TCP传输方式 2. TCP连…