Mark!20 個 .NET 6 新增的 API

Mark!20 個 .NET 6 新增的 API

DateOnly & TimeOnly

。NET 6 引入了兩種期待已久的型別 - DateOnly 和 TimeOnly, 它們分別代表

DateTime

的日期和時間部分。

DateOnly

dateOnly

=

new

2021

9

25

);

Console

WriteLine

dateOnly

);

TimeOnly

timeOnly

=

new

19

0

0

);

Console

WriteLine

timeOnly

);

DateOnly

dateOnlyFromDate

=

DateOnly

FromDateTime

DateTime

Now

);

Console

WriteLine

dateOnlyFromDate

);

TimeOnly

timeOnlyFromDate

=

TimeOnly

FromDateTime

DateTime

Now

);

Console

WriteLine

timeOnlyFromDate

);

Parallel。ForEachAsync

它可以控制多個非同步任務的並行度。

var

userHandlers

=

new

[]

{

“users/okyrylchuk”

“users/jaredpar”

“users/davidfowl”

};

using

HttpClient

client

=

new

()

{

BaseAddress

=

new

Uri

“https://api。github。com”

),

};

client

DefaultRequestHeaders

UserAgent

Add

new

ProductInfoHeaderValue

“DotNet”

“6”

));

ParallelOptions

options

=

new

()

{

MaxDegreeOfParallelism

=

3

};

await

Parallel

ForEachAsync

userHandlers

options

async

uri

token

=>

{

var

user

=

await

client

GetFromJsonAsync

<

GitHubUser

>(

uri

token

);

Console

WriteLine

$

“Name: {user。Name}\nBio: {user。Bio}\n”

);

});

public

class

GitHubUser

{

public

string

Name

{

get

set

}

public

string

Bio

{

get

set

}

}

// Output:

// Name: David Fowler

// Bio: Partner Software Architect at Microsoft on the ASP。NET team, Creator of SignalR

//

// Name: Oleg Kyrylchuk

// Bio: Software developer | Dotnet | C# | Azure

//

// Name: Jared Parsons

// Bio: Developer on the C# compiler

ArgumentNullException。ThrowIfNull()

ArgumentNullException 的小改進, 在丟擲異常之前不需要在每個方法中檢查 null, 現在只需要寫一行, 和

response。EnsureSuccessStatusCode();

類似。

ExampleMethod

null

);

void

ExampleMethod

object

param

{

ArgumentNullException

ThrowIfNull

param

);

// Do something

}

PriorityQueue

。NET 6 新增的資料結構, PriorityQueue, 佇列每個元素都有一個關聯的優先順序,它決定了出隊順序, 編號小的元素優先出列。

PriorityQueue

<

string

int

>

priorityQueue

=

new

();

priorityQueue

Enqueue

“Second”

2

);

priorityQueue

Enqueue

“Fourth”

4

);

priorityQueue

Enqueue

“Third 1”

3

);

priorityQueue

Enqueue

“Third 2”

3

);

priorityQueue

Enqueue

“First”

1

);

while

priorityQueue

Count

>

0

{

string

item

=

priorityQueue

Dequeue

();

Console

WriteLine

item

);

}

// Output:

// First

// Second

// Third 2

// Third 1

// Fourth

RandomAccess

提供基於偏移量的 API,用於以執行緒安全的方式讀取和寫入檔案。

using

SafeFileHandle

handle

=

File

OpenHandle

“file。txt”

access

FileAccess

ReadWrite

);

// Write to file

byte

[]

strBytes

=

Encoding

UTF8

GetBytes

“Hello world”

);

ReadOnlyMemory

buffer1

=

new

strBytes

);

await

RandomAccess

WriteAsync

handle

buffer1

0

);

// Get file length

long

length

=

RandomAccess

GetLength

handle

);

// Read from file

Memory

buffer2

=

new

new

byte

length

]);

await

RandomAccess

ReadAsync

handle

buffer2

0

);

string

content

=

Encoding

UTF8

GetString

buffer2

ToArray

());

Console

WriteLine

content

);

// Hello world

PeriodicTimer

認識一個完全非同步的“PeriodicTimer”, 更適合在非同步場景中使用, 它有一個方法

WaitForNextTickAsync

// One constructor: public PeriodicTimer(TimeSpan period)

using

PeriodicTimer

timer

=

new

TimeSpan

FromSeconds

1

));

while

await

timer

WaitForNextTickAsync

())

{

Console

WriteLine

DateTime

UtcNow

);

}

// Output:

// 13 - Oct - 21 19:58:05 PM

// 13 - Oct - 21 19:58:06 PM

// 13 - Oct - 21 19:58:07 PM

// 13 - Oct - 21 19:58:08 PM

// 13 - Oct - 21 19:58:09 PM

// 13 - Oct - 21 19:58:10 PM

// 13 - Oct - 21 19:58:11 PM

// 13 - Oct - 21 19:58:12 PM

// 。。。

Metrics API

。NET 6 實現了 OpenTelemetry Metrics API 規範, 內建了指標API, 透過 Meter 類建立下面的指標

•Counter

•Histogram

•ObservableCounter

•ObservableGauge

使用的方法如下:

var

builder

=

WebApplication

CreateBuilder

args

);

var

app

=

builder

Build

();

// Create Meter

var

meter

=

new

Meter

“MetricsApp”

“v1。0”

);

// Create counter

Counter

counter

=

meter

CreateCounter

“Requests”

);

app

Use

((

context

next

=>

{

// Record the value of measurement

counter

Add

1

);

return

next

context

);

});

app

MapGet

“/”

()

=>

“Hello World”

);

StartMeterListener

();

app

Run

();

// Create and start Meter Listener

void

StartMeterListener

()

{

var

listener

=

new

MeterListener

();

listener

InstrumentPublished

=

instrument

meterListener

=>

{

if

instrument

Name

==

“Requests”

&&

instrument

Meter

Name

==

“MetricsApp”

{

// Start listening to a specific measurement recording

meterListener

EnableMeasurementEvents

instrument

null

);

}

};

listener

SetMeasurementEventCallback

((

instrument

measurement

tags

state

=>

{

Console

WriteLine

$

“Instrument {instrument。Name} has recorded the measurement: {measurement}”

);

});

listener

Start

();

}

檢查元素是否可為空的反射API

它提供來自反射成員的可空性資訊和上下文:

•ParameterInfo 引數

•FieldInfo 欄位

•PropertyInfo 屬性

•EventInfo 事件

var

example

=

new

Example

();

var

nullabilityInfoContext

=

new

NullabilityInfoContext

();

foreach

var

propertyInfo

in

example

GetType

()。

GetProperties

())

{

var

nullabilityInfo

=

nullabilityInfoContext

Create

propertyInfo

);

Console

WriteLine

$

“{propertyInfo。Name} property is {nullabilityInfo。WriteState}”

);

}

// Output:

// Name property is Nullable

// Value property is NotNull

class

Example

{

public

string

Name

{

get

set

}

public

string

Value

{

get

set

}

}

檢查巢狀元素是否可為空的反射API

它允許您獲取巢狀元素的可為空的資訊, 您可以指定陣列屬性必須為非空,但元素可以為空,反之亦然。

Type

exampleType

=

typeof

Example

);

PropertyInfo

notNullableArrayPI

=

exampleType

GetProperty

nameof

Example

NotNullableArray

));

PropertyInfo

nullableArrayPI

=

exampleType

GetProperty

nameof

Example

NullableArray

));

NullabilityInfoContext

nullabilityInfoContext

=

new

();

NullabilityInfo

notNullableArrayNI

=

nullabilityInfoContext

Create

notNullableArrayPI

);

Console

WriteLine

notNullableArrayNI

ReadState

);

// NotNull

Console

WriteLine

notNullableArrayNI

ElementType

ReadState

);

// Nullable

NullabilityInfo

nullableArrayNI

=

nullabilityInfoContext

Create

nullableArrayPI

);

Console

WriteLine

nullableArrayNI

ReadState

);

// Nullable

Console

WriteLine

nullableArrayNI

ElementType

ReadState

);

// Nullable

class

Example

{

public

string

?[]

NotNullableArray

{

get

set

}

public

string

?[]?

NullableArray

{

get

set

}

}

ProcessId & ProcessPath

直接透過 Environment 獲取程序ID和路徑。

int

processId

=

Environment

ProcessId

string

path

=

Environment

ProcessPath

Console

WriteLine

processId

);

Console

WriteLine

path

);

Configuration 新增 GetRequiredSection()

和 DI 的 GetRequiredService() 是一樣的, 如果缺失, 則會丟擲異常。

WebApplicationBuilder

builder

=

WebApplication

CreateBuilder

args

);

WebApplication

app

=

builder

Build

();

MySettings

mySettings

=

new

();

// Throws InvalidOperationException if a required section of configuration is missing

app

Configuration

GetRequiredSection

“MySettings”

)。

Bind

mySettings

);

app

Run

();

class

MySettings

{

public

string

SettingValue

{

get

set

}

}

CSPNG 密碼安全偽隨機數生成器

您可以從密碼安全偽隨機數生成器 (CSPNG) 輕鬆生成隨機值序列。

它對於以下場景中很有用:

•金鑰生成

•隨機數

•某些簽名方案

// Fills an array of 300 bytes with a cryptographically strong random sequence of values。

// GetBytes(byte[] data);

// GetBytes(byte[] data, int offset, int count)

// GetBytes(int count)

// GetBytes(Span data)

byte

[]

bytes

=

RandomNumberGenerator

GetBytes

300

);

Native Memory API

。NET 6 引入了一個新的 API 來分配本機記憶體, NativeMemory 有分配和釋放記憶體的方法。

unsafe

{

byte

*

buffer

=

byte

*)

NativeMemory

Alloc

100

);

NativeMemory

Free

buffer

);

/* This class contains methods that are mainly used to manage native memory。

public

static

class

NativeMemory

{

public

unsafe

static

void

*

AlignedAlloc

nuint byteCount

nuint alignment

);

public

unsafe

static

void

AlignedFree

void

*

ptr

);

public

unsafe

static

void

*

AlignedRealloc

void

*

ptr

nuint byteCount

nuint alignment

);

public

unsafe

static

void

*

Alloc

nuint byteCount

);

public

unsafe

static

void

*

Alloc

nuint elementCount

nuint elementSize

);

public

unsafe

static

void

*

AllocZeroed

nuint byteCount

);

public

unsafe

static

void

*

AllocZeroed

nuint elementCount

nuint elementSize

);

public

unsafe

static

void

Free

void

*

ptr

);

public

unsafe

static

void

*

Realloc

void

*

ptr

nuint byteCount

);

}*/

}

Power of 2

。NET 6 引入了用於處理 2 的冪的新方法。

•‘IsPow2’ 判斷指定值是否為 2 的冪。

•‘RoundUpToPowerOf2’ 將指定值四捨五入到 2 的冪。

// IsPow2 evaluates whether the specified Int32 value is a power of two。

Console

WriteLine

BitOperations

IsPow2

128

));

// True

// RoundUpToPowerOf2 rounds the specified T:System。UInt32 value up to a power of two。

Console

WriteLine

BitOperations

RoundUpToPowerOf2

200

));

// 256

WaitAsync on Task

您可以更輕鬆地等待非同步任務執行, 如果超時會丟擲 “TimeoutException”

Task

operationTask

=

DoSomethingLongAsync

();

await

operationTask

WaitAsync

TimeSpan

FromSeconds

5

));

async

Task

DoSomethingLongAsync

()

{

Console

WriteLine

“DoSomethingLongAsync started。”

);

await

Task

Delay

TimeSpan

FromSeconds

10

));

Console

WriteLine

“DoSomethingLongAsync ended。”

);

}

// Output:

// DoSomethingLongAsync started。

// Unhandled exception。System。TimeoutException: The operation has timed out。

新的數學API

新方法:

•SinCos

•ReciprocalEstimate

•ReciprocalSqrtEstimate

新的過載:

•Min, Max, Abs, Sign, Clamp 支援

nint

和 nuint

•DivRem 返回一個元組, 包括商和餘數。

// New methods SinCos, ReciprocalEstimate and ReciprocalSqrtEstimate

// Simultaneously computes Sin and Cos

double

sin

double

cos

=

Math

SinCos

1。57

);

Console

WriteLine

$

“Sin = {sin}\nCos = {cos}”

);

// Computes an approximate of 1 / x

double

recEst

=

Math

ReciprocalEstimate

5

);

Console

WriteLine

$

“Reciprocal estimate = {recEst}”

);

// Computes an approximate of 1 / Sqrt(x)

double

recSqrtEst

=

Math

ReciprocalSqrtEstimate

5

);

Console

WriteLine

$

“Reciprocal sqrt estimate = {recSqrtEst}”

);

// New overloads

// Min, Max, Abs, Clamp and Sign supports nint and nuint

nint a

nint b

=

5

10

);

nint min

=

Math

Min

a

b

);

nint max

=

Math

Max

a

b

);

nint abs

=

Math

Abs

a

);

nint clamp

=

Math

Clamp

abs

min

max

);

nint sign

=

Math

Sign

a

);

Console

WriteLine

$

“Min = {min}\nMax = {max}\nAbs = {abs}”

);

Console

WriteLine

$

“Clamp = {clamp}\nSign = {sign}”

);

// DivRem variants return a tuple

int

quotient

int

remainder

=

Math

DivRem

2

7

);

Console

WriteLine

$

“Quotient = {quotient}\nRemainder = {remainder}”

);

// Output:

// Sin = 0。9999996829318346

// Cos = 0。0007963267107331026

// Reciprocal estimate = 0。2

// Reciprocal sqrt estimate = 0。4472135954999579

// Min = 5

// Max = 10

// Abs = 5

// Clamp = 5

// Sign = 1

// Quotient = 0

// Remainder = 2

CollectionsMarshal。GetValueRefOrNullRef

這個是在字典中迴圈或者修改結可變結構體時用, 可以減少結構的副本複製, 也可以避免字典重複進行雜湊計算,這個有點晦澀難懂,有興趣的可以看看這個

https://github。com/dotnet/runtime/issues/27062

Dictionary

<

int

MyStruct

>

dictionary

=

new

()

{

{

1

new

MyStruct

{

Count

=

100

}

}

};

int

key

=

1

ref

MyStruct

value

=

ref

CollectionsMarshal

GetValueRefOrNullRef

dictionary

key

);

// Returns Unsafe。NullRef() if it doesn‘t exist; check using Unsafe。IsNullRef(ref value)

if

(!

Unsafe

IsNullRef

ref

value

))

{

Console

WriteLine

value

Count

);

// Output: 100

// Mutate in-place

value

Count

++;

Console

WriteLine

value

Count

);

// Output: 101

}

struct

MyStruct

{

public

int

Count

{

get

set

}

}

ConfigureHostOptions

IHostBuilder 上的新 ConfigureHostOptions API, 可以更簡單的配置應用。

public

class

Program

{

public

static

void

Main

string

[]

args

{

CreateHostBuilder

args

)。

Build

()。

Run

();

}

public

static

IHostBuilder

CreateHostBuilder

string

[]

args

=>

Host

CreateDefaultBuilder

args

ConfigureHostOptions

o

=>

{

o

ShutdownTimeout

=

TimeSpan

FromMinutes

10

);

});

}

Async Scope

。NET 6 引入了一種新的

CreateAsyncScope

方法, 當您處理 IAsyncDisposable 的服務時現有的

CreateScope

方法會引發異常, 使用 CreateAsyncScope 可以完美解決。

await

using

var

provider

=

new

ServiceCollection

()

AddScoped

<

Example

>()

BuildServiceProvider

();

await

using

var

scope

=

provider

CreateAsyncScope

())

{

var

example

=

scope

ServiceProvider

GetRequiredService

<

Example

>();

}

class

Example

IAsyncDisposable

{

public

ValueTask

DisposeAsync

()

=>

default

}

加密類簡化

•DecryptCbc

•DecryptCfb

•DecryptEcb

•EncryptCbc

•EncryptCfb

•EncryptEcb

static

byte

[]

Decrypt

byte

[]

key

byte

[]

iv

byte

[]

ciphertext

{

using

Aes

aes

=

Aes

Create

())

{

aes

Key

=

key

return

aes

DecryptCbc

ciphertext

iv

PaddingMode

PKCS7

);

}

}

[1] Oleg Kyrylchuk: https://hashnode。com/@okyrylchuk

文章來源於全球技術精選 ,作者Oleg Kyrylchuk