在C#中启用模式的语法是什么?

时间:2011-09-27 11:44:47

标签: c# c#-5.0

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>以外的其他内容。

所以我的问题是双重的,

  1. Anders正在谈论的模式是什么,还是我误解了什么?答案应该介于WinRT提供的类型之间,这与IAsyncFoo和未发布的规范有关。
  2. C#中是否还有其他此类模式(可能已存在)?

3 个答案:

答案 0 :(得分:7)

草案已发布 - 您可以从Visual Studio home page下载。异步模式是在driis的答案中给出的模式 - 您还可以阅读我的Eduasync blog series以获取更多详细信息,this post专用于该模式。

请注意,此模式适用于“您可以等待的内容”。异步方法必须返回voidTaskTask<T>

就C#中除了最初提到的集合初始化程序之外的其他模式而言:

  • foreach可以迭代非IEnumerable实现,只要该类型有GetEnumerator方法返回具有MoveNext()Current成员的类型
  • LINQ query expressions决定拨打SelectWhereGroupBy等电话。

答案 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();
    }
}