В последнее время я предпочел отображать отношения 1-1, используя Dictionaries
вместо Switch
операторов. Я считаю, что это немного быстрее писать и легче мысленно обрабатывать. К сожалению, при сопоставлении с новым экземпляром объекта я не хочу определять его следующим образом:
var fooDict = new Dictionary<int, IBigObject>()
{
{ 0, new Foo() }, // Creates an instance of Foo
{ 1, new Bar() }, // Creates an instance of Bar
{ 2, new Baz() } // Creates an instance of Baz
}
var quux = fooDict[0]; // quux references Foo
Учитывая эту конструкцию, я потратил впустую циклы ЦП и память, создавая 3 объекта, делая то, что могли содержать их конструкторы, и в итоге использовал только один из них. Я также считаю, что сопоставление других объектов fooDict[0]
в этом случае приведет к тому, что они будут ссылаться на одну и ту же вещь, а не на создание нового экземпляра, Foo
как предполагалось. Решение было бы использовать вместо этого лямбда:
var fooDict = new Dictionary<int, Func<IBigObject>>()
{
{ 0, () => new Foo() }, // Returns a new instance of Foo when invoked
{ 1, () => new Bar() }, // Ditto Bar
{ 2, () => new Baz() } // Ditto Baz
}
var quux = fooDict[0](); // equivalent to saying 'var quux = new Foo();'
Это доходит до того, что это слишком запутанно? Это легко пропустить ()
в конце. Или отображение на функцию / выражение является довольно распространенной практикой? Альтернативой было бы использовать переключатель:
IBigObject quux;
switch(someInt)
{
case 0: quux = new Foo(); break;
case 1: quux = new Bar(); break;
case 2: quux = new Baz(); break;
}
Какой вызов более приемлем?
- Словарь, для быстрого поиска и меньше ключевых слов (case and break)
- Переключатель: чаще встречается в коде, не требует использования объекта Func <> для косвенного обращения.
источник
fooDict[0] is fooDict[0]
). как с лямбдой, так и с переключателем это не такОтветы:
Это интересный взгляд на заводскую модель . Мне нравится сочетание словаря и лямбда-выражения; это заставило меня взглянуть на этот контейнер по-новому.
Я игнорирую беспокойство в вашем вопросе о циклах процессора, как вы упомянули в комментариях, что не-лямбда-подход не обеспечивает то, что вам нужно.
Я думаю, что любой подход (переключатель против словаря + лямбда) будет в порядке. Единственное ограничение заключается в том, что при использовании Словаря вы ограничиваете типы входных данных, которые вы можете получить для генерации возвращаемого класса.
Использование оператора switch обеспечит вам большую гибкость при вводе параметров. Однако, если это станет проблемой, вы можете заключить словарь в метод и получить тот же конечный результат.
Если это ново для вашей команды, прокомментируйте код и объясните, что происходит. Позвоните для обзора кода команды, проведите их через то, что было сделано, и сообщите им об этом. Кроме того, это выглядит хорошо.
источник
case 0: quux = new Foo(); break;
становитесьcase 0: return new Foo();
откровенно простыми и намного проще для чтения, чем{ 0, () => new Foo() }
C # 4.0 предоставляет вам
Lazy<T>
класс, который похож на ваше собственное второе решение, но более явно выкрикивает «Ленивая инициализация».источник
Стилистически я думаю, что читаемость одинакова между ними. Проще внедрить зависимости с помощью
Dictionary
.Не забывайте, что вы должны проверить, существует ли ключ при использовании
Dictionary
, и должны предоставить запасной вариант, если это не так.Я бы предпочел
switch
оператор для статических путей кода иDictionary
для динамических путей кода (где вы можете добавлять или удалять записи). Компилятор может выполнить некоторые статические оптимизации с тем,switch
что он не может сDictionary
.Интересно, что этот
Dictionary
шаблон - то, что люди иногда делают в Python, потому что в Python отсутствуетswitch
утверждение. В противном случае они используют цепочки if-else.источник
В общем, я бы предпочел ни того, ни другого.
Все, что потребляет это должно работать с
Func<int, IBigObject>
. Тогда источником вашего сопоставления может быть Словарь или метод, который имеет оператор switch, вызов веб-службы или какой-либо поиск файла ... что угодно.Что касается реализации, я бы предпочел словарь, поскольку его легче реорганизовать из «словаря жесткого кода, ключа поиска, возвращаемого результата» в «загрузить словарь из файла, ключа поиска, вернуть результат».
источник