2015-04-21 2 views
22

В настоящее время кодирования в C#, мне интересно, если есть способ учитывать код, представленные нижеИзбегайте несколько вызовов функций в C#

Entity1 = GetByName("EntityName1"); 
Entity2 = GetByName("EntityName2"); 
Entity3 = GetByName("EntityName3"); 

Идея заключается в том, чтобы получить один вызов в коде, факторинг код, поместив entities и strings в контейнер и итерации на этом контейнере, чтобы получить единственную линию «GetByName()». Есть ли способ сделать это?

+1

Помимо того факта, что для обеспечения рабочего кода нет темы, сложно улучшить код без дополнительной информации. Возможно, вы можете использовать словарь '. –

+0

Это зависит от того, как вы намереваетесь их использовать, вы можете использовать простой цикл, но неясно, что вы ожидаете от них после этого. – Sayse

+0

э-э-э, вот для чего нужен цикл. – Jodrell

ответ

27

Вы можете использовать LINQ:

var names=new[]{"EntityName1","EntityName2","EntityName3",.....}; 
var entities=names.Select(name=>GetByName(name)).ToArray(); 

Без ToArray, Select возвращает IEnumerable, который будет reevalueated каждый раз, когда вы перечислить его - то есть, GetByName будет вызываться каждый раз, когда вы перечислить перечислимое.

ToArray() или ToList будет создавать массив (или список), который вы можете использовать несколько раз.

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

var entities=names.ToDictionary(name=>name,name=>GetByName(name)); 

Все это предполагает, что объекты не существуют или что GetByName должен сделать некоторые значительную работу по извлеките их. Если сущности существуют, вы можете просто положить их в Dictionary<String,Entity>. Если субъекты имеют Name свойство можно использовать ToDictionary для создания словаря в одном заявлении:

var entities=new []{entity1,entity2,entity3,...}; 
var entitiesDict=entities.ToDictionary(entity=>entity.Name,entity=>entity); 
+7

Так почему бы не использовать 'Dictionary ' в первую очередь, если они так сильно зависят друг от друга? Тогда метод 'GetByName', коллекции' names' и 'entities' и этот запрос LINQ являются избыточными. –

+0

@TimSchmelter вы делаете несколько предположений, хотя вопрос * является неопределенным. Я предполагаю, что существует большое или различное количество имен, и OP не хочет иметь одну строку для каждого вызова - это то, чего избегает оператор LINQ. Я также предполагаю, что объект еще не существует или что 'GetByName' выполняет некоторую значительную работу по его извлечению. –

+0

@PanagiotisKanavos: и потому, что вам нужно сделать дополнения, этот вопрос не является чистым вообще. Рефакторинг кода также не соответствует теме, поэтому он может опубликовать его на [stackexchange.com] (http://codereview.stackexchange.com/). –

10

ли вы имеете в виду что-то вроде ниже (где entities является коллекция Entity1, Entity1 & Entity3):

var results = entities.Select(e => GetByName(e.Name)); 
7

Это зависит от того, что вы ищете. Если вам нужно установить переменные в одной строке, это не сработает. Вы можете играть с отражением, если имеете дело с полями или свойствами, но, честно говоря, это кажется более беспорядочным, чем то, что у вас уже есть.

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

Если вы хотите сделать это, это довольно прямолинейно. Это ваш выбор, как вы создаете IEnumerable<string>, который представлен ниже как entityNames. Вы можете использовать инициализатор массива, как и я, вы можете использовать List<string>, который вы строите с течением времени, вы можете даже yield return его по своему методу.

var entityNames = new[] { "EntityName1", "EntityName2", "EntityName3" }; 

var dict = entityNames.ToDictionary(c => c, c => GetByName(c)); 

Тогда это вопрос проверки.

var entity1 = dict["EntityName1"]; 

Или перечислить словарь.

foreach(var kvp in dict) 
{ 
    Console.WriteLine("{0} - {1}", kvp.Key, kvp.Value); 
} 

Но в реальности трудно понять, предпочтительнее ли это, что у вас уже есть.

3

Хорошо, вот идея.

Вы можете объявить эту функцию.

IReadOnlyDictionary<string, T> InstantiateByName<T>(
     Func<string, T> instantiator 
     params string[] names) 
{ 
    return names.Distinct().ToDictionary(
     name => name, 
     name => instantiator(name)) 
} 

, который можно было бы назвать так,

var entities = InstantiateByName(
     GetByName, 
     "EntityName1", 
     "EntityName2", 
     "EntityName3"); 

Чтобы подтолкнуть над инженерии к следующему уровню,

вы можете установить пакет Неизменного Коллекции,

PM> Install-Package Microsoft.Bcl.Immutable 

и изменить функцию слегка,

using Microsoft.Immutable.Collections; 

IReadOnlyDictionary<string, T> InstantiateByName<T>(
     Func<string, T> instantiator 
     params string[] names, 
     IEqualityComparer<string> keyComparer = null, 
     IEqualityComparer<T> valueComparer = null) 
{ 
    if (keyComparer == null) 
    { 
     keyComparer = EqualityComparer<string>.Default; 
    } 

    if (valueComparer == null) 
    { 
     valueComparer = EqualityComparer<T>.Default; 
    } 

    return names.ToImmutableDictionary(
     name => name, 
     name => instantiator(name), 
     keyComparer, 
     valueComparer); 
} 

Функция будет использоваться точно так же. Тем не менее, вызывающий отвечает за передачу уникальных ключей функции, но может быть передан альтернативный сопоставитель.

Смежные вопросы