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#中是否有其他类似的模式(可能已经存在)?

c#中支持语法的模式是什么?

规范草案已发布 -您可以从Visual Studio主页下载。异步模式在driis的回答中给出了——你也可以阅读我的Eduasync博客系列了解更多细节,这篇文章是专门讨论这个模式的。

注意这个模式只有适用于"what you can await"。async方法必须返回voidTaskTask<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();
    }
}