当前位置:网站首页>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;
}
}
边栏推荐
- In action: 10 ways to implement delayed tasks, with code!
- 【数据分析】:什么是数据分析?
- setup syntax sugar defineProps defineEmits defineExpose
- Wintun:一款惊艳的 WireGuard 虚拟网卡接口驱动
- Axure9的元件用法
- 【软件工程导论】软件工程导论笔记
- callback prototype __proto__
- Golang source code analysis: time/rate
- Lvm逻辑卷
- Leetcode刷题——单调栈问题(739每日温度问题、496下一个更大元素I、503下一个更大元素 II)
猜你喜欢
Meta 与苹果的元宇宙碰撞
Translate My Wonderful | July Moli Translation Program Winners Announced
Parse common methods in the Collection interface that are overridden by subclasses
Day35 LeetCode
J9 digital theory: the Internet across chain bridge has what effect?
Parse the commonly used methods in the List interface that are overridden by subclasses
J9 Digital Currency Theory: Identifying Web3's New Scarcity: Open Source Developers
OP-5,输入/输出信号范围-一信号处理能力
Shell: conditional statements
基于 outline 实现头像剪裁以及预览
随机推荐
Qt提升自定义控件,找不到头文件
Axure9的元件用法
信息学奥赛一本通(1258:【例9.2】数字金字塔)
ssdp协议搜索GB28181设备
Meta 与苹果的元宇宙碰撞
Parse common methods in the Collection interface that are overridden by subclasses
The so-called fighting skill again gao also afraid of the chopper - partition, depots, table, and the merits of the distributed
传感器工作原理
线程安全(上)
五大维度解读软件测试分类
顺序查找和折半查找,看这篇就够了
Day35 LeetCode
什么是乙二醇二乙酸酯(EGDA)?
C# Barrier class
Linphone 被叫方如何解析来电SIP消息中的自定义头消息
「 每日一练,快乐水题 」1374. 生成每种字符都是奇数个的字符串
磁盘分区的知识
OP-5,输入/输出信号范围-一信号处理能力
SQL Server安装教程
信息系统项目管理师必背核心考点(五十八)变更管理的主要角色