当前位置:网站首页>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;
}
}
边栏推荐
- 基本语法(三)
- 开关、电机、断路器、电热偶、电表接线图大全
- Parse the commonly used methods in the List interface that are overridden by subclasses
- 传感器工作原理
- Likou Question of the Day - Day 46 - 344. Reverse Strings
- Meta 与苹果的元宇宙碰撞
- SQL 入门之第一讲——MySQL 8.0.29安装教程(windows 64位)
- 李沐动手学深度学习V2-BERT预训练和代码实现
- Translate My Wonderful | July Moli Translation Program Winners Announced
- 二丙二醇甲醚醋酸酯
猜你喜欢

PG's SQL execution plan

Translate My Wonderful | July Moli Translation Program Winners Announced

基于 outline 实现头像剪裁以及预览

LeetCode:622. 设计循环队列【模拟循环队列】

李沐动手学深度学习V2-bert和代码实现

特拉维夫大学 | Efficient Long-Text Understanding with Short-Text Models(使用短文本模型进行高效的长文本理解)

Fiddle设置接口数据用指定工具查看;Sublime Text设置json数据格式化转换

实现fashion_minst服装图像分类

iframe------------frame-

浅议.NET遗留应用改造
随机推荐
LeetCode:622. 设计循环队列【模拟循环队列】
56.【全局变量和局部变量专题】
信息学奥赛一本通(1257:Knight Moves)
Translate My Wonderful | July Moli Translation Program Winners Announced
【软件工程导论】软件工程导论笔记
网上那么多教人赚钱的方法,但是你实际上是靠什么赚钱的呢?
SQL Server实现group_concat功能
AI Scientist: Automatically discover hidden state variables of physical systems
信息学奥赛一本通(1260:【例9.4】拦截导弹(Noip1999))
【数据分析】:什么是数据分析?
In action: 10 ways to implement delayed tasks, with code!
笑话:如果你在河边等待得足够久,你会看到你的敌人的尸体漂过,是怎么翻译出来的?
Geoserver+mysql+openlayers2
Day35 LeetCode
遇上Mysql亿级优化,怎么办
Geoip2 - golang golang source code analysis
ECCV 2022 | 通往数据高效的Transformer目标检测器
Implement fashion_minst clothing image classification
ACE JET NPOI
setup syntax sugar defineProps defineEmits defineExpose