当前位置:网站首页>Details in C# you don't know
Details in C# you don't know
2022-08-02 23:33:00 【biyusr】
前言
有一个东西叫做鸭子类型,所谓鸭子类型就是,只要一个东西表现得像鸭子那么就能推出这玩意就是鸭子.
C# 里面其实也暗藏了很多类似鸭子类型的东西,但是很多开发者并不知道,因此也就没法好好利用这些东西,So today I'll take a closer look at the details hidden in the compiler.
不是只有 Task
和 ValueTask
才能 await
在 C# when writing asynchronous code,We often choose to include async code in one Task
或者 ValueTask
中,That way the caller can use it await
way to implement asynchronous calls.
西卡西,并不是只有 Task
和 ValueTask
才能 await
.Task
和 ValueTask
Behind the scenes, the thread pool is clearly involved in scheduling,可是为什么 C# 的 async
/await
But it was said to be coroutine
呢?
because of you await
Something doesn't have to be Task
/ValueTask
,在 C# as long as your class contains GetAwaiter()
方法和 bool IsCompleted
属性,并且 GetAwaiter()
The returned thing contains one GetResult()
方法、一个 bool IsCompleted
properties and implementations INotifyCompletion
,Then the object of this class is OK await
的 .
因此在封装 I/O 操作的时候,我们可以自行实现一个 Awaiter
,It's based on the underlying epoll
/IOCP
实现,这样当 await
will not create any threads,Nor will any thread scheduling occur,Rather, it simply cedes control.而 OS 在完成 I/O 调用后通过 CompletionPort
(Windows) Wait until the user mode is notified to complete the asynchronous call,At this point the context is restored to continue executing the remaining logic,This is actually a real one stackless coroutine
.
Copy
public class MyTask<T>
{
public MyAwaiter<T> GetAwaiter()
{
return new MyAwaiter<T>();
}
}
public class MyAwaiter<T> : INotifyCompletion
{
public bool IsCompleted { get; private set; }
public T GetResult()
{
throw new NotImplementedException();
}
public void OnCompleted(Action continuation)
{
throw new NotImplementedException();
}
}
public class Program
{
static async Task Main(string[] args)
{
var obj = new MyTask<int>();
await obj;
}
}
事实上,.NET Core 中的 I/O related asynchrony API 也的确是这么做的,I/O During the operation, there will be no thread allocation waiting for the result,都是 coroutine
操作:I/O Relinquish control directly after the operation starts,直到 I/O 操作完毕.And the reason why sometimes you find out await
The front and rear threads have changed,那只是因为 Task
itself is scheduled.
UWP used in development IAsyncAction
/IAsyncOperation<T>
It is the encapsulation from the bottom layer,和 Task
It doesn't matter but it's okay await
的,并且如果用 C++/WinRT 开发 UWP 的话,It is also possible to return methods of these interfaces co_await
的.
不是只有 IEnumerable
和 IEnumerator
才能被 foreach
Often we will write the following code:
Copy
foreach (var i in list)
{
// ......
}
Then ask why foreach
,Most will reply because of this list
实现了 IEnumerable
或者 IEnumerator
.
但是实际上,An object can be used if desired foreach
,只需要提供一个 GetEnumerator()
方法,并且 GetEnumerator()
The returned object contains one bool MoveNext()
方法加一个 Current
属性即可.
Copy
class MyEnumerator<T>
{
public T Current { get; private set; }
public bool MoveNext()
{
throw new NotImplementedException();
}
}
class MyEnumerable<T>
{
public MyEnumerator<T> GetEnumerator()
{
throw new NotImplementedException();
}
}
class Program
{
public static void Main()
{
var x = new MyEnumerable<int>();
foreach (var i in x)
{
// ......
}
}
}
不是只有 IAsyncEnumerable
和 IAsyncEnumerator
才能被 await foreach
同上,But this time the requirements have changed,GetEnumerator()
和 MoveNext()
变为 GetAsyncEnumerator()
和 MoveNextAsync()
.
其中 MoveNextAsync()
The thing returned should be one Awaitable<bool>
,至于这个 Awaitable
到底是什么,它可以是 Task
/ValueTask
,It can also be other or your own implementation.
Copy
class MyAsyncEnumerator<T>
{
public T Current { get; private set; }
public MyTask<bool> MoveNextAsync()
{
throw new NotImplementedException();
}
}
class MyAsyncEnumerable<T>
{
public MyAsyncEnumerator<T> GetAsyncEnumerator()
{
throw new NotImplementedException();
}
}
class Program
{
public static async Task Main()
{
var x = new MyAsyncEnumerable<int>();
await foreach (var i in x)
{
// ......
}
}
}
ref struct
要怎么实现 IDisposable
众所周知 ref struct
Because it must be on the stack and cannot be boxed,So the interface cannot be implemented,但是如果你的 ref struct
中有一个 void Dispose()
那么就可以用 using
The syntax implements the automatic destruction of objects.
Copy
ref struct MyDisposable
{
public void Dispose() => throw new NotImplementedException();
}
class Program
{
public static void Main()
{
using var y = new MyDisposable();
// ......
}
}
不是只有 Range
才能使用切片
C# 8 引入了 Ranges,Slicing operations are allowed,But it is not necessary to provide a reception Range
类型参数的 indexer to use this feature.
As long as your class can be counted(拥有 Length
或 Count
属性),and can be sliced(拥有一个 Slice(int, int)
方法),Then you can use this feature.
Copy
class MyRange
{
public int Count { get; private set; }
public object Slice(int x, int y) => throw new NotImplementedException();
}
class Program
{
public static void Main()
{
var x = new MyRange();
var y = x[1..];
}
}
不是只有 Index
才能使用索引
C# 8 引入了 Indexes 用于索引,例如使用 ^1
索引倒数第一个元素,But it is not necessary to provide a reception Index
类型参数的 indexer to use this feature.
As long as your class can be counted(拥有 Length
或 Count
属性),并且可以被索引(have a receive int
参数的索引器),Then you can use this feature.
Copy
class MyIndex
{
public int Count { get; private set; }
public object this[int index]
{
get => throw new NotImplementedException();
}
}
class Program
{
public static void Main()
{
var x = new MyIndex();
var y = x[^1];
}
}
Implement destructuring for types
How to implement destructuring for a type?In fact, only need to write a name as Deconstruct()
的方法,并且参数都是 out
的即可.
Copy
class MyDeconstruct
{
private int A => 1;
private int B => 2;
public void Deconstruct(out int a, out int b)
{
a = A;
b = B;
}
}
class Program
{
public static void Main()
{
var x = new MyDeconstruct();
var (o, u) = x;
}
}
Not just realized IEnumerable
才能用 LINQ
LINQ
是 C# An integrated query language commonly used in ,Allows you to write code like this:
Copy
from c in list where c.Id > 5 select c;
但是上述代码中的 list
The type does not necessarily have to be implemented IEnumerable
,事实上,As long as there is an extension method with the corresponding name,For example, there is called Select
method can be used select
,have a called Where
method can be used where
.
Copy
class Just<T> : Maybe<T>
{
private readonly T value;
public Just(T value) { this.value = value; }
public override Maybe<U> Select<U>(Func<T, Maybe<U>> f) => f(value);
public override string ToString() => $"Just {value}";
}
class Nothing<T> : Maybe<T>
{
public override Maybe<U> Select<U>(Func<T, Maybe<U>> _) => new Nothing<U>();
public override string ToString() => "Nothing";
}
abstract class Maybe<T>
{
public abstract Maybe<U> Select<U>(Func<T, Maybe<U>> f);
public Maybe<V> SelectMany<U, V>(Func<T, Maybe<U>> k, Func<T, U, V> s)
=> Select(x => k(x).Select(y => new Just<V>(s(x, y))));
public Maybe<U> Where(Func<Maybe<T>, bool> f) => f(this) ? this : new Nothing<T>();
}
class Program
{
public static void Main()
{
var x = new Just<int>(3);
var y = new Just<int>(7);
var z = new Nothing<int>();
var u = from x0 in x from y0 in y select x0 + y0;
var v = from x0 in x from z0 in z select x0 + z0;
var just = from c in x where true select c;
var nothing = from c in x where false select c;
}
}
边栏推荐
- 你是几星测试/开发程序员?技术型选手王大拿......
- ssdp协议搜索GB28181设备
- Solve the docker mysql can't write Chinese
- Geoip2 - golang golang source code analysis
- LeetCode - 105. 从前序与中序遍历序列构造二叉树;023.合并K个升序链表
- golang source code analysis: uber-go/ratelimit
- 力扣每日一题-第46天-344. 反转字符串
- 信息学奥赛一本通(1258:【例9.2】数字金字塔)
- 56.【全局变量和局部变量专题】
- DataGrip 安装教程 详细版
猜你喜欢
用了TCP协议,就一定不会丢包吗?
奥特学园ROS笔记--7(289-325节)
Digital twins help visualize the construction of smart cities
牛客题目——滑动窗口的最大值、矩阵最长递增路径、顺时针旋转矩阵、接雨水问题
Triacetin是什么化学材料
pytorch的tensor创建和操作记录
基于 outline 实现头像剪裁以及预览
美国爱荷华州立大学| Improving Distantly Supervised Relation Extraction by Natural Language Inference(通过自然语言推理改进远程监督关系提取)
模板的进阶
J9 Digital Currency Theory: Identifying Web3's New Scarcity: Open Source Developers
随机推荐
OP analysis and design
PLC工作原理动画
如何使用windbg查看C#某个线程的栈大小 ?
LM小型可编程控制器软件(基于CoDeSys)笔记二十五:plc的数据存储区(数字量输入通道部分)
基于“无依赖绝对定位”实现的圣杯三栏布局
Meta 与苹果的元宇宙碰撞
OP-5,输入/输出信号范围-一信号处理能力
网上那么多教人赚钱的方法,但是你实际上是靠什么赚钱的呢?
Parse common methods in the Collection interface that are overridden by subclasses
Common tools and test methods for interface testing (Introduction)
成为黑客不得不学的语言,看完觉得你们还可吗?
Lvm逻辑卷
ImageNet下载及处理
Axure9的元件用法
封装和包、访问修饰权限
Shell: conditional statements
顺序查找和折半查找,看这篇就够了
「每周译Go」这次我们来点不一样的!--《How to Code in Go》系列上线
Linphone 被叫方如何解析来电SIP消息中的自定义头消息
第一次进入前20名