Подтвердить что ты не робот

Есть ли название для этого шаблона? (С# с компиляцией типа-безопасности с параметрами "params" разных типов)

Есть ли имя для этого шаблона?

Предположим, вы хотите создать метод, который принимает переменное количество аргументов, каждый из которых должен быть одним из фиксированного набора типов (в любом порядке или комбинации), а некоторые из этих типов вы не контролируете. Общим подходом было бы заставить ваш метод принимать аргументы типа Object и проверять типы во время выполнения:

void MyMethod (params object[] args)
{
    foreach (object arg in args)
    {
        if (arg is SomeType)
            DoSomethingWith((SomeType) arg);
        else if (arg is SomeOtherType)
            DoSomethingElseWith((SomeOtherType) arg);
        // ... etc.
        else throw new Exception("bogus arg");
    }
}

Однако скажите, что, как и я, вы одержимы безопасностью типа времени компиляции и хотите иметь возможность проверять типы аргументов метода во время компиляции. Здесь подход, который я придумал:

void MyMethod (params MyArg[] args)
{
    // ... etc.
}

struct MyArg
{
    public readonly object TheRealArg;

    private MyArg (object obj) { this.TheRealArg = obj; }

    // For each type (represented below by "GoodType") that you want your 
    // method to accept, define an implicit cast operator as follows:

    static public implicit operator MyArg (GoodType x)
    { return new MyArg(x); }

}

Неявные отбрасывания позволяют передавать аргументы действительных типов непосредственно в вашу подпрограмму без необходимости их явного литья или их переноса. Если вы попытаетесь передать значение недопустимого типа, ошибка будет обнаружена во время компиляции.

Я уверен, что другие использовали этот подход, поэтому мне интересно, есть ли имя для этого шаблона.

4b9b3361

Ответ 1

Кажется, что нет имени именованного шаблона в Interwebs, но на основе Ryan комментария к вашему вопросу, я проголосую за название шаблона Variadic Типы безопасности.

В общем, я бы использовал его очень экономно, но я не считаю шаблон хорошим или плохим. Многие из комментаторов сделали хорошие пункты pro и con, которые мы видим для других шаблонов, таких как Factory, Locator, Injection Dependency, MVVM и т.д. Это все о контексте. Итак, вот удар...

Контекст

Необходимо обработать переменный набор разрозненных объектов.

Использовать, когда

  • Ваш метод может принимать переменное количество аргументов разрозненных типов, которые не имеют общего базового типа.
  • Ваш метод широко используется (т.е. во многих местах в коде и/или множестве пользователей вашей инфраструктуры). Дело в том, что безопасность типов обеспечивает достаточную выгоду, чтобы гарантировать ее использование.
  • Аргументы могут передаваться в любом порядке, но набор разрозненных типов конечен и единственный набор, приемлемый для метода.
  • Выразительность - это ваша цель дизайна, и вы не хотите ставить бремя на пользователя для создания оберток или адаптеров (см. Альтернативы).

Реализация

Вы уже указали это.

<сильные > Примеры

  • LINQ to XML (например, new XElement(...))
  • Другие разработчики, такие как те, которые строят параметры SQL.
  • Процессорные фасады (например, те, которые могут принимать разные типы делегатов или объекты команд из разных фреймворков) для выполнения команд без необходимости создания явных командных адаптеров.

Альтернативы

  • адаптер. Примите переменное количество аргументов некоторого типа адаптера (например, Adapter<T> или подклассы не общего Adapter), с которым метод может работать, чтобы получить желаемые результаты. Это расширяет набор, который может использовать ваш метод (типы перестают быть конечными), но ничего не теряется, если адаптер делает все возможное, чтобы обработка продолжала работать. Недостатком является то, что у пользователя есть дополнительное бремя определения существующих и/или создания новых адаптеров, что, возможно, умаляет намерение (т.е. Добавляет "церемонию" и ослабляет "сущность" ).
  • Снимите защиту типа. Это подразумевает принятие очень базового типа (например, Object) и размещение проверок времени выполнения. Бремя о том, что нужно знать, передается пользователю, но код все еще выразителен. Ошибки не отображаются до времени выполнения.
  • Composite. Передайте один объект, который является составной частью других. Для этого требуется предварительная сборка вызова метода, но она возвращается к использованию одного из приведенных выше шаблонов для элементов в составной коллекции.
  • Свободный API. Замените единый вызов серией конкретных вызовов, по одному для каждого допустимого аргумента. Канонический пример: StringBuilder.

Ответ 2

Он называется анти-паттерн, более известный как Poltergeist.

Update:

Если типы args всегда постоянны и порядок не имеет значения, тогда создайте перегрузки, каждая из которых принимает коллекции (IEnumerable <T> ), изменяя T в каждом методе для типа, в котором вы должны работать. Это уменьшит сложность кода:

  • Удаление класса MyArg
  • устраняя необходимость в литье типов в MyMethod
  • добавит дополнительную безопасность типа времени компиляции, поскольку если вы попытаетесь вызвать метод со списком аргументов, которые вы не можете обработать, вы получите исключение компилятора.

Ответ 3

Это выглядит как подмножество Композитный шаблон. Цитата из Википедии:

Составной шаблон описывает, что группа объектов должна обрабатываться так же, как один экземпляр объекта.