Мне нужно преобразовать список значений int
в список значений enum
и наоборот. Я могу создать простой метод преобразования, но хотел посмотреть, есть ли более краткий способ справиться с этим.
Вот как выглядят мои значения перечисления:
public enum AutoShipOption
{
Monthly = 2,
Weekly = 1,
Yearly = 3,
Undefined = 0
}
И в моем классе, который я использую для определения элемента магазина, я получаю List<int>
, который мне нужно преобразовать в List<AutoShipOption>
. Как я уже сказал, легко создать простой метод, который будет обрабатывать эту проблему и который будет выглядеть следующим образом:
public List<AutoShipOption> AutoShipOptionsMapper(List<int> values)
{
var options = new List<AutoShipOption>();
if (values == null || values.Count == 0)
return options;
foreach(var item in values)
if (item > 0)
options.Add((AutoShipOption)item);
return options;
}
Есть ли более краткий способ справиться с этим преобразованием?
I need to convert a list of int values to list of enum values and vice versa
, я вижу только попытку преобразовать список int в список перечислений, вам тоже нужен список перечислений в список int?
@Стив. Кратко? Какова семантика AutoShipOptionsMapper
? if (item > 0)
Я часто критикую собеседования по шаблонному кодированию, потому что, если ваши данные содержат значения, которые не имеют смысла — что это значит? Вероятно, вам нужна ошибка, а не игнорирование мусора. (Это не сопоставление, а фильтрация — остерегайтесь своего имени). Кроме того, иногда вы получаете один и тот же (пустой) список, а иногда — новый список. Безопасно ли добавлять в список (нет), так почему бы не вернуть массив? Имейте в виду, что с точки зрения языка допустимо, чтобы перечисление AutoShipOption содержало любое целое значение.
Вы можете использовать LINQ Cast, как показано ниже:
var ints = new List<int> { 0, 1, 2, 3 };
var enums = ints
.Where(x => Enum.IsDefined<AutoShipOption>(x))
.Cast<AutoShipOption>()
.ToList();
Такой метод можно инкапсулировать в некоторые общие методы расширения для IEnumerable
и List
:
public static class EnumEnumerableExtensions
{
public static List<T> SafeListCast<T>(this List<T> list)
where T : struct, Enum
{
return list.SafeCast().ToList();
}
public static IEnumerable<T> SafeCast<T>(this IEnumerable<T> enumerable)
where T : struct, Enum
{
return enumerable
.Where(Enum.IsDefined)
.Cast<T>();
}
}
Тогда пример будет упрощен:
var ints = new List<int> { 0, 1, 2, 3 };
var enums = ints.SafeListCast<AutoShipOption>();
Это преобразуется в IEnumerable<AutoShipOption>
, а не в List<AutoShipOption>
. Вам нужно будет написать ints.Cast<AutoShipOption>().ToList()
Что произойдет, если в этом решении для перечисления не существует значения? См. ответ SELA ниже, чтобы узнать что-то менее подверженное ошибкам.
@Trevor Я следовал «подверженному ошибкам» подходу, применил ОП, и это предположило, что это безопасно. Я сосредоточился на простоте, которая была главной целью. Тем не менее, это исправил.
Это все, что нужно через LINQ:
public static List<AutoShipOption> AutoShipOptionsMapper(List<int> values)
{
if (values == null)
return new List<AutoShipOption>();
return values
.Where(item => Enum.IsDefined(typeof(AutoShipOption), item))
.Select(item => (AutoShipOption)item)
.ToList();
}
См. полный код ниже:
using System;
using System.Collections.Generic;
using System.Linq;
namespace EnumConversion
{
public enum AutoShipOption
{
Monthly = 2,
Weekly = 1,
Yearly = 3,
Undefined = 0
}
class Program
{
static void Main(string[] args)
{
List<int> intValues = new List<int> { 1, 2, 3, 4, 0, -1 };
List<AutoShipOption> enumValues = AutoShipOptionsMapper(intValues);
Console.WriteLine("AutoShipOptions values:");
foreach (var option in enumValues)
{
Console.WriteLine(option);
}
}
public static List<AutoShipOption> AutoShipOptionsMapper(List<int> values)
{
if (values == null)
return new List<AutoShipOption>();
return values
.Where(item => Enum.IsDefined(typeof(AutoShipOption), item))
.Select(item => (AutoShipOption)item)
.ToList();
}
}
}
См. рабочий .netfiddle здесь
Возможно ли, чтобы List<int> содержал недопустимые значения перечисления?