20個 .NET 6 新增的 API

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(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 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 filebyte[] strBytes = Encoding。UTF8。GetBytes(“Hello world”);ReadOnlyMemory buffer1 = new(strBytes);await RandomAccess。WriteAsync(handle, buffer1, 0);// Get file lengthlong length = RandomAccess。GetLength(handle);// Read from fileMemory 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 Metervar meter = new Meter(“MetricsApp”, “v1。0”);// Create counterCounter 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 Listenervoid 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 NotNullclass 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); // NotNullConsole。WriteLine(notNullableArrayNI。ElementType。ReadState); // NullableNullabilityInfo nullableArrayNI = nullabilityInfoContext。Create(nullableArrayPI);Console。WriteLine(nullableArrayNI。ReadState); // NullableConsole。WriteLine(nullableArrayNI。ElementType。ReadState); // Nullableclass Example{ public string?[] NotNullableArray { get; set; } public string?[]? NullableArray { get; set; }}

ProcessId & ProcessPath

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

int processId = Environment。ProcessIdstring 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 missingapp。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 / xdouble 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 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() 。BuildServiceProvider();await using (var scope = provider。CreateAsyncScope()){ var example = scope。ServiceProvider。GetRequiredService();}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); }}

全文完…

作者: Oleg Kyrylchuk

原文: https://blog。okyrylchuk。dev/