Попробуйте это класс:
public class TestIt
{
public static T[] Convert<T>(string delimitedValues)
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException();
}
if (delimitedValues == string.Empty)
{
return new T[0];
}
string[] parts = delimitedValues.Split(',');
T[] converted = Array.ConvertAll(parts, x => (T)Enum.Parse(typeof(T), x));
return converted;
}
}
По соглашению вы используете T
в качестве родового параметра вместо T[]
использовать его как:
TestValues[] values = TestIt.Convert<TestValues>("Unknown,Pizza");
Вы можете сделать это даже с одним меньше гипса:
public static T[] Convert<T>(string delimitedValues) where T : struct
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException();
}
if (delimitedValues == string.Empty)
{
return new T[0];
}
string[] parts = delimitedValues.Split(',');
T[] converted = new T[parts.Length];
for (int i = 0; i < parts.Length; i++)
{
if (!Enum.TryParse(parts[i], out converted[i]))
{
throw new FormatException(parts[i]);
}
}
return converted;
}
Если вы хотите, вы можете даже иметь версию, которая будет возвращать T?[]
(так что массив нулевых перечислений)
public static T?[] ConvertNullable<T>(string delimitedValues) where T : struct
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException();
}
if (delimitedValues == string.Empty)
{
return new T[0];
}
string[] parts = delimitedValues.Split(',');
T?[] converted = new T?[parts.Length];
for (int i = 0; i < parts.Length; i++)
{
if (parts[i] == string.Empty)
{
continue;
}
T value;
if (!Enum.TryParse(parts[i], out value))
{
throw new FormatException(parts[i]);
}
converted[i] = value;
}
return converted;
}
Использовать его как;
TestValues?[] values = TestIt.ConvertNullable<TestValues>(",Unknown,,Pizza,");
Обратите внимание, что эта последняя версия не пропускает «недопустимые» значения, она все равно бросает на них. Просто он преобразует string.Empty
элементов в null
. К сожалению, есть проблема: если вы ConvertNullable<TestValues>(string.Empty)
, он вернет TestValues[0]
, но эту строку можно даже преобразовать в TestValues[1] { null }
.
Теперь, если вы действительно хотите пиццу со всем:
public static class EnumSplitter
{
public static T[] Convert<T>(string delimitedValues) where T : struct
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException();
}
if (delimitedValues == string.Empty)
{
return new T[0];
}
string[] parts = delimitedValues.Split(',');
T[] converted = new T[parts.Length];
for (int i = 0; i < parts.Length; i++)
{
if (!Enum.TryParse(parts[i], out converted[i]))
{
throw new FormatException(parts[i]);
}
}
return converted;
}
public static TArray ConvertArray<TArray>(string delimitedValues) where TArray : IList
{
return MethodCache<TArray>.Convert(delimitedValues);
}
public static T?[] ConvertNullable<T>(string delimitedValues) where T : struct
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException();
}
if (delimitedValues == string.Empty)
{
return new T?[0];
}
string[] parts = delimitedValues.Split(',');
T?[] converted = new T?[parts.Length];
for (int i = 0; i < parts.Length; i++)
{
if (parts[i] == string.Empty)
{
continue;
}
T value;
if (!Enum.TryParse(parts[i], out value))
{
throw new FormatException(parts[i]);
}
converted[i] = value;
}
return converted;
}
public static TArray ConvertNullableArray<TArray>(string delimitedValues) where TArray : IList
{
return MethodCache<TArray>.Convert(delimitedValues);
}
private static class MethodCache<TArray> where TArray : IList
{
public static readonly Func<string, TArray> Convert;
static MethodCache()
{
if (!typeof(TArray).IsArray)
{
throw new ArgumentException("TArray");
}
Type element = typeof(TArray).GetElementType();
Type element2 = Nullable.GetUnderlyingType(element);
if (element2 == null)
{
Convert = (Func<string, TArray>)Delegate.CreateDelegate(typeof(Func<string, TArray>), typeof(EnumSplitter).GetMethod("Convert").MakeGenericMethod(element));
}
else
{
Convert = (Func<string, TArray>)Delegate.CreateDelegate(typeof(Func<string, TArray>), typeof(EnumSplitter).GetMethod("ConvertNullable").MakeGenericMethod(element2));
}
}
}
}
Я использую MethodCache<>
класс для кэширования вызов отражения «право» Convert<>
метода.
Использование:
TestValues[] arr1 = EnumSplitter.Convert<TestValues>("Unknown,Pizza");
TestValues?[] arr2 = EnumSplitter.ConvertNullable<TestValues>("Unknown,,Pizza,");
TestValues[] arr3 = EnumSplitter.ConvertArray<TestValues[]>("Unknown,Pizza");
TestValues?[] arr4 = EnumSplitter.ConvertNullableArray<TestValues?[]>("Unknown,,Pizza,");
Вы действительно не должны использовать 'var' за все, что собирается сделать это остов для отладки - кроме того, что по этому поводу решения не работает? –
@EBrown 'var' не затрудняет отладку. – CodeCaster
@CodeCaster Это вопрос мнения, в этой ** ситуации это может иметь минимальное влияние, но если он привык использовать 'var' всюду, он столкнется с нечетными проблемами в будущем, где это неопределенно почему решение не сработало. То есть Тип-несоответствия и т. Д. Да, это отлично подходит для анонимных типов, но определенно должно быть ** не ** быть по умолчанию «go-to» или «catch-all», когда он его использует. –