c#中支持语法的模式是什么?
本文关键字:模式 是什么 语法 支持 | 更新日期: 2023-09-27 18:09:41
c#语言有几个模式特性,即类不需要从特定的接口派生;而是为了使用一些c#语法/特性而实现一个特定的模式。
让我们考虑一个例子:
public class MyCollection : IEnumerable
{
public T Add(T name, T name2, ...) { }
public IEnumerator GetEnumerator() { return null; }
}
这里,TYPE
是任意类型。基本上,我们有一个实现IEnumerable
的类,并有一个名为Add()
的方法,该方法具有任意数量的参数。
这样可以声明一个新的MyCollection
实例:
new MyCollection{{a1, a2, ...}, {b1, b2, ...} }
相当于:
var mc = new MyCollection();
mc.Add(a1, a1, ...);
mc.Add(b1, b2, ...);
神奇!与此同时,最近(我相信是在BUILD活动期间)Anders Hejlsberg无意中透露,新的await/async
也将使用模式实现,这使得WinRT可以返回Task<T>
以外的东西。
我的问题是双重的
- 安德斯说的是什么模式,还是我误解了什么?答案应该介于WinRT提供的类型之间,类似于
IAsyncFoo
和未发布的规范。c#中是否有其他类似的模式(可能已经存在)?规范草案已发布 -您可以从Visual Studio主页下载。异步模式在driis的回答中给出了——你也可以阅读我的Eduasync博客系列了解更多细节,这篇文章是专门讨论这个模式的。
注意这个模式只有适用于"what you can await"。async方法必须返回void
、Task
或Task<T>
。
在c#中除了你最初提到的集合初始化器之外的其他模式:
-
foreach
可以迭代非ienumerable实现,只要该类型具有返回具有MoveNext()
和Current
成员的类型的GetEnumerator
方法 - LINQ查询表达式解析为对
Select
,Where
,GroupBy
等的调用
对于async
,它适用于awaiter模式,我认为Stephen Toub在这里描述得最好:
"语言支持等待任何公开正确方法(实例方法或扩展方法)的实例:GetAwaiter。GetAwaiter需要返回一个自身公开三个成员的类型:"
bool IsCompleted { get; }
void OnCompleted(Action continuation);
TResult GetResult(); // TResult can also be void
作为一个例子,在异步CTP中,Task的GetAwaiter方法返回一个TaskAwaiter类型的值:
public struct TaskAwaiter
{
public bool IsCompleted { get; }
public void OnCompleted(Action continuation);
public void GetResult();
}
如果你想要async
的所有细节,开始阅读Jon Skeets关于async
的帖子。他们对这个问题进行了详细的讨论。
除了你提到的基于模式的集合初始化器之外,c#中另一个基于模式的特性是LINQ:对于LINQ关键字,所需要的只是重载解析找到具有正确名称和签名的实例或扩展方法。看看Eric lippert关于这个主题的文章。而且,foreach
是基于模式的——Eric也在链接的文章中描述了这个模式的细节。
另一个可以使用的模式是using关键字。如果你有一个实现IDisposable
的类,那么你可以说:
using(Resource myResource = GetResource())
{
}
翻译过来类似于::
Resource myResource;
try
{
myResource = GetResource();
}
finally
{
var disposable = myResource as IDisposable;
if(disposable != null) disposable.Dispose()
}
虽然我认为它没有foreach
或查询操作符那么"神奇",但它是一个相对不错的语法。
同样地,你可以使用yield return
来自动地为你实现一个迭代器。
public struct SimpleBitVector32 : IEnumerable<bool>
{
public SimpleBitVector32(uint value)
{
this.data = value;
}
private uint data;
public bool this[int offset]
{
get
{
unchecked
{
return (this.data & (1u << offset)) != 0;
}
}
set
{
unchecked
{
this.data = value ? (this.data | (1u << offset)) : (this.data & ~(1u << offset));
}
}
}
public IEnumerator<bool> GetEnumerator()
{
for (int i = 0; i < 32; i++)
{
yield return this[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}