Каковы шаблоны включения синтаксиса в C #? - PullRequest
3 голосов
/ 27 сентября 2011

Существует несколько паттернов-особенностей языка 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), Андерс Хейлсберг допустил, что новый await/async будет реализован с использованием шаблонова также, что позволяет WinRT уйти с возвратом чего-то отличного от Task<T>.

Так что мой вопрос двоякий:

  1. Каков паттерн, о котором говорил Андерс, или ячто-то не так понял?Ответ должен быть где-то между типом WinRT, что-то вроде IAsyncFoo и неопубликованной спецификацией.
  2. Существуют ли какие-либо другие подобные шаблоны (возможно, уже существующие) в C #?

Ответы [ 3 ]

7 голосов
/ 27 сентября 2011

Проект спецификации опубликован - его можно загрузить с домашней страницы Visual Studio .Шаблон для асинхронности - тот, который приведен в ответе Драйса. Вы также можете прочитать мою серию блогов Eduasync для получения более подробной информации, с этой записью , посвященной шаблону.* Обратите внимание, что этот шаблон только относится к «что вы можете ждать».Асинхронный метод должен вернуть void, Task или Task<T>.

С точки зрения других шаблонов в C # помимо инициализатора коллекции, который вы упомянули первоначально:

  • foreach может выполнять итерации для не-IEnumerable реализаций, при условии, что тип имеет метод GetEnumerator, возвращающий тип, имеющий MoveNext() и Current членов
  • выражений запросов LINQ разрешить звонки на Select, Where, GroupBy и т. Д.
6 голосов
/ 27 сентября 2011

Для async он работает по шаблону awaiter , который, я думаю, лучше всего описан здесь, Стивеном Тубом :

" Языки поддерживают ожидание любого экземпляра, который предоставляет правильный метод (либо метод экземпляра, либо метод расширения): GetAwaiter. GetAwaiter должен возвращать тип, который сам предоставляет три члена: "

bool IsCompleted { get; }
void OnCompleted(Action continuation);
TResult GetResult(); // TResult can also be void

В качестве примера этого в Async CTP метод GetAwaiter для Task возвращает значение типа TaskAwaiter:

public struct TaskAwaiter 
{ 
    public bool IsCompleted { get; }
    public void OnCompleted(Action continuation); 
    public void GetResult(); 
}

Если вы хотите узнать все подробности async, начните , читая сообщения Джона Скитса о async. Они подробно рассказывают о предмете.


Помимо инициализаторов коллекций, основанных на шаблонах, как вы упомянули, еще одна функция на основе шаблонов в C # - это LINQ: для ключевых слов LINQ требуется только то, чтобы при разрешении перегрузки был найден метод экземпляра или расширения с правильными именем и сигнатурой. Взгляните на статью Эрика Липпертса на эту тему . Кроме того, foreach основан на шаблонах - Эрик также подробно описывает этот шаблон в связанной статье.

2 голосов
/ 27 сентября 2011

Другой шаблон, который вы можете использовать, это ключевое слово 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();
    }
}
...