欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.NET 6新增的20个API介绍

程序员文章站 2022-03-13 18:53:10
dateonly & timeonly.net 6 引入了两种期待已久的类型 - dateonly 和 timeonly, 它们分别代表datetime的日期和时间部分。dateonly da...

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<byte> buffer1 = new(strbytes);
await randomaccess.writeasync(handle, buffer1, 0);

// get file length
long length = randomaccess.getlength(handle);

// read from file
memory<byte> 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<int> counter = meter.createcounter<int>("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<int>((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<byte> 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<tvalue>() 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);
    }
}

到此这篇关于.net 6新增的20个api介绍的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。