hez2010の日常

kekekekekekeke

Tag: C#

新しい関数ポインタの機能を試しましょう

はじめに .NET 5には新しい機能「関数ポインタ」を追加されました。これは、ネイティブ相互運用を改善し、パフォーマンスを上げるために作られました。 関数ポインタは下位レベルのデリゲートで、関数呼び出しのより効率的な方法を提供します。既知の方法にSystem.Action<>, System.Func<>といい、System.Delegateといい、どちらもオーバーヘッドがたくさんあります。でも関数ポインタはそういうオーバーエンドがありません。 さらに関数ポインタはマネージ関数のみをサポートすることではなく、アンマネージ関数もサポートされています。だからこそ、ネイティブ相互運用を行う場合は、関数ポインタを使用すると非常に便利になります。 じゃ、早速始めましょう。 使い方 関数ポインタの型の形式は delegate* + managed/unmanaged + [呼び出し規則(ネイティブのみ)]+<パラメータリスト(void を使えます)>です。例えば: 言語宣言関数ポインタの型C++void __cdecl f()delegate* unmanaged[Cdecl]<void>C++void __cdecl f(int)delegate* unmanaged[Cdecl]<int, void>C++int __cdecl f(int)delegate* unmanaged[Cdecl]<int, int>C#static string f(int)delegate* managed<int, string>C#static void f(string)delegate* managed<string, void> [Cdecl] のみではなく、[Stdcall]と[Fastcall]と[Thiscall]も使えますよ。 アンマネージ関数の使い方 まずはネイティブ相互運用を紹介しましょう。 C++コードを書けます: #define WIN32 #define UNICODE #include <cstring> #include <cstdio> extern “C” __declspec(dllexport) // C# 関数はパラメーター gen […]

Read More

新版 C# 高效率编程指南

前言 C# 从 7 版本开始一直到如今的 9 版本,加入了非常多的特性,其中不乏改善性能、增加程序健壮性和代码简洁性、可读性的改进,这里我整理一些使用新版 C# 的时候个人推荐的写法,可能不适用于所有的人,但是还是希望对你们有所帮助。 注意:本指南适用于 .NET 5 或以上版本。 使用 ref struct 做到 0 GC C# 7 开始引入了一种叫做 ref struct 的结构,这种结构本质是 struct ,结构存储在栈内存。但是与 struct 不同的是,该结构不允许实现任何接口,并由编译器保证该结构永远不会被装箱,因此不会给 GC 带来任何的压力。相对的,使用中就会有不能逃逸出栈的强制限制。 Span<T> 就是利用 ref struct 的产物,成功的封装出了安全且高性能的内存访问操作,且可在大多数情况下代替指针而不损失任何的性能。 ref struct MyStruct { public int Value { get; set; } } class RefStructGuide { static void Test() { […]

Read More

.NET 异步解说

前言 要了解 .NET 中的 async/await 机制,首先需要有操作系统原理的基础,否则的话是很难理解清楚的,如果没有这些基础而试图向他人解释,大多也只是基于现象得到的错误猜想。 初看异步 说到异步大家应该都很熟悉了,2012 年 C# 5 引入了新的异步机制:Task,并且还有两个新的关键字 await 和 async,这已经不是什么新鲜事了,而且如今这个异步机制已经被各大语言借鉴,如 JavaScript、TypeScript、Rust、C++ 等等。 下面给出一个简单的对照: 语言调度单位关键字/方法C#Task<>、ValueTask<>async、awaitC++std::future<>co_awaitRuststd::future::Future<>.awaitJavaScript、TypeScriptPromise<>async、await 当然,这里这并不是本文的重点,只是提一下,方便大家在有其他语言经验的情况下(如果有),可以认识到 C# 中 Task 和 async/await 究竟是一个和什么可以相提并论的东西。 多线程编程 在该异步编程模型诞生之前,多线程编程模型是很多人所熟知的。一般来说,开发者会使用 Thread、std::thread 之类的东西作为线程的调度单位来进行多线程开发,每一个这样的结构表示一个对等线程,线程之间采用互斥或者信号量等方式进行同步。 多线程对于科学计算速度提升等方面效果显著,但是对于 IO 负荷的任务,例如从读取文件或者 TCP 流,大多数方案只是分配一个线程进行读取,读取过程中阻塞该线程: void Main() { while (true) { var client = socket.Accept(); new Thread(() => ClientThread(client)).Start(); } } void ClientThread(Socket client) { […]

Read More

你所不知道的 C# 中的细节

前言 有一个东西叫做鸭子类型,所谓鸭子类型就是,只要一个东西表现得像鸭子那么就能推出这玩意就是鸭子。 C# 里面其实也暗藏了很多类似“鸭子类型”的东西,但是很多开发者并不知道,因此也就没法好好利用这些东西,那么今天我细数一下这些藏在编译器中的细节。 至于为什么 C# 要这么做,其实有部分的原因是为了让不能实现接口的 ref struct 也能实现对应的功能。 不是只有 Task 和 ValueTask 才能 await 在 C# 中编写异步代码的时候,我们经常会选择将异步代码包含在一个 Task 或者 ValueTask 中,这样调用者就能用 await 的方式实现异步调用。 西卡西,并不是只有 Task 和 ValueTask 才能 await。Task 和 ValueTask 背后明明是由线程池参与调度的,可是为什么 C# 的 async/await 却被说成是 coroutine 呢? 因为你所 await 的东西不一定是 Task/ValueTask,在 C# 中只要你的类中包含 GetAwaiter() 方法和 bool IsCompleted 属性,并且 GetAwaiter() 返回的东西包含一个 GetResult() 方法、一个 […]

Read More

C# 9 新特性:代码生成器、编译时反射

前言 今天 .NET 官方博客宣布 C# 9 Source Generators 第一个预览版发布,这是一个用户已经喊了快 5 年特性,今天终于发布了。 简介 Source Generators 顾名思义代码生成器,它允许开发者在代码编译过程中获取查看用户代码并且生成新的 C# 代码参与编译过程,并且可以很好的与代码分析器集成提供 Intellisense、调试信息和报错信息,可以用它来做代码生成,因此也相当于是一个加强版本的编译时反射。 使用 Source Generators,可以做到这些事情: 获取一个 Compilation 对象,这个对象表示了所有正在编译的用户代码,你可以从中获取 AST 和语义模型等信息可以向 Compilation 对象中插入新的代码,让编译器连同已有的用户代码一起编译 Source Generators 作为编译过程中的一个阶段执行: 编译运行 -> [分析源代码 -> 生成新代码] -> 将生成的新代码添加入编译过程 -> 编译继续。 上述流程中,中括号包括的内容即为 Source Generators 所参与的阶段和能做到的事情。 作用 .NET 明明具备运行时反射和动态 IL 织入功能,那这个 Source Generators 有什么用呢? 编译时反射 – 0 […]

Read More