当前位置: 首页 > news >正文

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

相关文章:

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

目录 Whats new in C# 7 C# 7 in Visual Studio 2017 Out Variables Pattern Matching Tuples &#xff08;System.ValueTuple&#xff09; Deconstruct解构 Local Functions Ref Returns and Locals Expression Bodied Members Throw Expressions Generated Async R…...

Sqlserver常用sql

1. 数据库和表操作 创建数据库 CREATE DATABASE DatabaseName; 删除数据库 DROP DATABASE DatabaseName; 创建表 CREATE TABLE TableName ( Column1 DataType1, Column2 DataType2, ... ); 删除表 DROP TABLE TableName; 2. 数据操作 插入数据 INSERT INTO TableNam…...

基于SpringBoot+Vue+MySQL的考研互助交流平台

系统展示 用户前台界面 管理员后台界面 系统背景 本文设计并实现了一个基于SpringBoot、Vue.js和MySQL的考研互助交流平台。该平台旨在为广大考研学子提供一个集资源共享、学习交流、经验分享、心理辅导等功能于一体的综合性在线社区。通过SpringBoot构建高效稳定的后端服务&am…...

chatgpt个人版ssrf漏洞

文章目录 免责申明搜索语法漏洞描述漏洞复现修复建议 免责申明 本文章仅供学习与交流&#xff0c;请勿用于非法用途&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 搜索语法 fofa title"ChatGPT个人专用版"漏洞描述 该系统是一个开源的…...

如何查看微信聊天记录?四种实用方法查询微信聊天记录,赶快码住!

微信作为我们日常生活中不可或缺的社交工具&#xff0c;记录了大量的聊天内容和重要信息。 当需要查看或恢复微信聊天记录时&#xff0c;很多人可能不知道如何快速、安全地进行操作。 今天&#xff0c;我们就来介绍四种实用的微信聊天记录查询方法&#xff0c;帮助你有效查看微…...

钢材表面缺陷数据集以coco格式做好了数据集的划分,1200张训练集,600张验证集,对应的json文件也在里面

钢材表面缺陷数据集 以coco格式做好了数据集的划分&#xff0c;1200张训练集&#xff0c;600张验证集&#xff0c;对应的json文件也在里面。 钢材表面缺陷检测数据集营销介绍 项目背景&#xff1a; 钢材作为工业生产的重要原材料之一&#xff0c;其表面质量直接影响到成品的性…...

【Lua坑】Lua协程coroutine无法正常完整执行问题

问题&#xff1a;发现Lua协程执行到一半&#xff0c;突然被掐断了一样等到了设定的时间没有正常执行协程后续代码&#xff01;非必现bug&#xff0c;若发生大概率在高频率使用协程时易触发。 LuaFramework或xLua uLua都自带有协程coroutine&#xff0c;而且基本都使用对象池缓…...

istio中serviceentry结合egressgateway的使用

假设有一个外部服务&#xff0c;外部服务ip为&#xff1a;10.10.102.90&#xff0c;其中32033为v1版本&#xff0c;32034为v2版本。 现在需要把这个服务引入到istio中&#xff0c;并且需要配置所有访问该服务的流量都通过egressgateway转发出去。 serviceentry apiVersion: n…...

使用 Python 实现 Windows 应用图标的便捷生成:一站式 PNG 转 ICO 工具20240918

使用 Python 实现 Windows 应用图标的便捷生成&#xff1a;一站式 PNG 转 ICO 工具 在开发 Windows 桌面应用程序时&#xff0c;图标文件&#xff08;ICO&#xff09;的生成是不可忽视的关键步骤。无论是任务栏图标、快捷方式&#xff0c;还是应用程序的主图标&#xff0c;都需…...

编程环境常用命令合集

cmd: python 进入python运行环境 exit()/quit()/ctrlZ 退出环境 rmdir /s venv 删除环境 pip命令&#xff1a; pip list 查看所有库 pip install <库> 安装库 -i <数据源>可指定安装数据源 pip install <库>x.x.x 安装指定版本的库 pip install --upgrade &…...

Qt Creator 集成开发环境 常见问题

1.QtCreator中三种不同编译版本 debug、release、profile 的区别 在 Qt Creator 中&#xff0c;Debug、Release 和 Profile 是三种不同的构建配置&#xff0c;它们主要用于在开发过程中生成不同类型的可执行文件。它们的区别如下&#xff1a; 1.1 Debug&#xff08;调试版本&…...

使用Faiss进行K-Means聚类

&#x1f4dd; 本文需要的前置知识&#xff1a;Faiss的基本使用 目录 1. 源码剖析1.1 参数解释 2. 聚类过程详解2.1 初始化聚类中心2.2 分配步骤&#xff08;Assignment&#xff09;2.3 更新步骤&#xff08;Update&#xff09;2.4 收敛与终止条件 3. GPU 加速3.1 索引结构与 G…...

通过hosts.allow和hosts.deny限制用户登录

1、Hosts.allow和host.deny说明 两个文件是控制远程访问设置的&#xff0c;通过设置这个文件可以允许或者拒绝某个ip或者ip段的客户访问linux的某项服务。如果请求访问的主机名或IP不包含在/etc/hosts.allow中&#xff0c;那么tcpd进程就检查/etc/hosts.deny。看请求访问的主机…...

PWN College 关于sql盲注

在这个场景中&#xff0c;我们需要利用SQL注入漏洞来泄露flag&#xff0c;但是应用程序并不会直接返回查询结果。相反&#xff0c;我们需要根据应用程序的行为差异&#xff08;登录成功与否&#xff09;来推断查询结果。这就是所谓的"布尔盲注"&#xff08;Boolean-b…...

【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连…...

员工疯狂打CALL!解锁企业微信新玩法,2024年必学秘籍来啦!

现在工作离不开电脑手机&#xff0c;公司交流也得用新招。腾讯出了个企业微信&#xff0c;就是给公司用的聊天工具。它功能强大&#xff0c;操作简便&#xff0c;很多公司用它来让工作更高效&#xff0c;团队合作更紧密。接下来&#xff0c;我会简单说说怎么上手企业微信&#…...

Spring boot从0到1 - day01

前言 Spring 框架作为 Java 领域中最受欢迎的开发框架之一&#xff0c;提供了强大的支持来帮助开发者构建高性能、可维护的 Web 应用。 学习目标 Spring 基础 Spring框架是什么&#xff1f;Spring IoC与Aop怎么理解&#xff1f; Spring Boot 的快速构建 Spring 基础 学习…...

Flutter 项目结构的区别

如果需要调用原生代码&#xff0c;请创建一个plugin类型的项目开发。如果需要调用C语言&#xff0c;请参考文档&#xff1a;Flutter项目中调用C语言plugin 其实是 package 的一种&#xff0c;全称是 plugin package&#xff0c;我们简称为 plugin&#xff0c;中文叫插件。 1. A…...

EfficientFormerV2:重新思考视觉变换器以实现与MobileNet相当的尺寸和速度。

摘要 https://arxiv.org/pdf/2212.08059 随着视觉变换器&#xff08;ViTs&#xff09;在计算机视觉任务中的成功&#xff0c;近期的研究尝试优化ViTs的性能和复杂度&#xff0c;以实现在移动设备上的高效部署。提出了多种方法来加速注意力机制&#xff0c;改进低效设计&#xf…...

ASP.NET Core高效管理字符串集合

我们在开发 Web 项目时经常遇到需要管理各种来源的字符串集合&#xff08;例如HTTP 标头、查询字符串、设置的值等&#xff09;的情况。合理的管理这些字符串集合不仅可以减少出bug的几率&#xff0c;也能提高应用程序的性能。ASP.NET Core 为我们提供了一种特殊的只读结构体 S…...

vm-tools的卸载重装,只能复制粘贴,无法拖拽文件!

开始 ubuntu22.04 LTSVMwareTools-10.3.25-20206839.tar.gzVMware Workstation 17 Pro 各种该尝试的配置都尝试了,比如: 1.开启复制粘贴拖拽; 2.VMware Tools拖拽失效; 3.解决VMware无法拖拽. 均没有奏效. 安装过程报错, 报错异常: The installation of VMware Tools 10.3.25…...

Docker 容器网络技术

Docker 容器网络技术 一、概述 Docker 容器技术在微服务架构和云原生应用中扮演着重要角色。容器的轻量化和快速启动特性&#xff0c;使得它们成为现代应用部署的首选。然而&#xff0c;容器的网络连接和管理是一个复杂的问题&#xff0c;尤其是当涉及到容器间通信时。Docker…...

C++ 起始帧数、结束帧数、剪辑视频

C 指定起始帧数、结束帧数、 剪辑视频 C 无法直接用H264&#xff0c;只能用avi编码格式 #include <iostream> #include <opencv2/opencv.hpp>int main() {// 读取视频&#xff1a;创建了一个VideoCapture对象&#xff0c;参数为摄像头编号std::string path &quo…...

【项目一】基于pytest的自动化测试框架———解读requests模块

解读python的requests模块 什么是requests模块基础用法GET与POST的区别数据传递格式会话管理与持久性连接处理相应结果应对HTTPS证书验证错误处理与异常捕获 这篇blog主要聚焦如何使用 Python 中的 requests 模块来实现接口自动化测试。下面我介绍一下 requests 的常用方法、数…...

升级Ubuntu内核的几种方法

注意&#xff1a; Ubuntu主线内核由 Ubuntu 内核团队提供&#xff0c;用于测试和调试目的。 它们不受支持且不适合生产使用。 仅当它们可以解决当前内核遇到的关键问题时&#xff0c;才应该安装它们。 1、手动下载deb文件升级内核 来源&#xff1a;kernel.ubuntu.com/main…...

Android绘制靶面,初步点击位置区域划分取值测试

自定义View&#xff1a; public class TargetView extends View {private Paint paint;private int[] radii {100, 250, 400, 550, 700}; // 五个圆的半径private int numberOfSegments 8;private int[][] regionValues; // 存储每个区域的值public TargetView(Context cont…...

【SpringBoot】调度和执行定时任务--Quartz(超详细)

Quartz 是一个功能强大的任务调度框架&#xff0c;广泛用于在 Java 应用程序中定时执行任务&#xff0c;同时它支持 Cron 表达式、持久化任务、集群等特性。以下是 Quartz 的详细使用教程&#xff0c;包括安装、基本概念、简单示例和高级功能。 1. 安装 Quartz 首先&#xff…...

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

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

源码编译llama.cpp 、ggml 后端启用自定义BLAS加速

源码编译llama.cpp 、ggml 后端启用自定义BLAS加速 我在llama.cpp 官网上提交了我的解决方案&#xff1a;How to setup OpenBlas on windows? #625 GGML 官网 https://github.com/ggerganov/ggml/issues/959 windows on arm 编译 llama.cpp 、ggml 后端启用自定义BLAS加速 …...

glb数据格式

glb数据格式 glb 文件格式只包含一个glb 文件&#xff0c;文件按照二进制存储&#xff0c;占空间小 浏览 浏览glb工具的很多&#xff0c;ccs&#xff0c;3D查看器等都可以&#xff0c;不安装软件的话用下面网页加载就可以&#xff0c;免费 glTF Viewer (donmccurdy.com) glb…...