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>
以外的其他内容。
所以我的问题是双重的,
IAsyncFoo
和未发布的规范有关。答案 0 :(得分:7)
草案已发布 - 您可以从Visual Studio home page下载。异步模式是在driis的答案中给出的模式 - 您还可以阅读我的Eduasync blog series以获取更多详细信息,this post专用于该模式。
请注意,此模式仅适用于“您可以等待的内容”。异步方法必须返回void
,Task
或Task<T>
。
就C#中除了最初提到的集合初始化程序之外的其他模式而言:
foreach
可以迭代非IEnumerable实现,只要该类型有GetEnumerator
方法返回具有MoveNext()
和Current
成员的类型Select
,Where
,GroupBy
等电话。答案 1 :(得分:6)
对于async
,它适用于 awaiter模式,我认为is described best here, by Stephen Toub:
“语言支持等待暴露正确方法的任何实例(实例方法或扩展方法):GetAwaiter.GetAwaiter需要返回一个本身暴露三个成员的类型:”
bool IsCompleted { get; }
void OnCompleted(Action continuation);
TResult GetResult(); // TResult can also be void
作为示例,在Async CTP中,Task的GetAwaiter方法返回TaskAwaiter类型的值:
public struct TaskAwaiter
{
public bool IsCompleted { get; }
public void OnCompleted(Action continuation);
public void GetResult();
}
如果您需要async
的所有详细信息,请启动reading Jon Skeets posts about async
。他们详细介绍了这个主题。
除了你提到的基于模式的集合初始化器之外,C#中另一个基于模式的特性是LINQ:对于LINQ关键字,所需要的只是重载解析找到具有正确名称和签名的实例或扩展方法。看看Eric Lipperts article about the subject。此外,foreach
基于模式--Eric还在链接文章中描述了此模式的详细信息。
答案 2 :(得分:2)
您可以使用的另一种模式是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();
}
}