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

Избегайте нескольких вызовов функций в С#

В настоящее время кодирование на С#, интересно, есть ли способ кодировать код, представленный ниже

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

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

4b9b3361

Ответ 1

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

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

Без ToArray, Select вернет IEnumerable, который будет повторно проверяться каждый раз, когда вы его перечисляете, то есть 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);

Ответ 2

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

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

Ответ 3

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

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

Если вы хотите сделать это, это довольно прямолинейно. Это ваш выбор, как вы создаете 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);
}

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

Ответ 4

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

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

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");

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

вы можете установить пакет Immutable Collections,

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);
}

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