простой вопрос:-
у меня есть следующее простое если (..) операторы:-
if (foo == Animal.Cat || foo == Animal.Dog)
{ .. }
if (baa == 1|| baa == 69)
{ .. }
действительно ли возможно осуществить рефакторинг их во что-то как...
Отказ от ответственности: Я знаю, что это не компилирует.. но это - вид того, что я пытаюсь получить...
if (foo == (Animal.Cat || Animal.Dog))
{ .. }
if (baa == (1 || 69))
{ .. }
Аплодисменты :)
Интересно, могло ли расширение лямбда-выражения сделать это?:P
Обычно я создаю метод расширения под названием IsIn ()
, который принимает общий массив параметров типа
, а затем вызывает .Contains ()
для это, передавая экземпляр, на котором вызывается расширение.
Похоже, if (foo.IsIn (foo1, foo2))
. Очень просто писать, очень легко использовать.
В этом конкретном случае, когда у вас есть только два варианта, от этого мало толку, но если их может быть много, вы можете поместить их в список а затем используйте Contains
следующим образом:
List<Animal> allowedAnimals = new List<Animal>
{
Animal.Cat,
Animal.Dog,
Animal.Fish,
Animal.Frog,
Animal.Horse
};
if (allowedAnimals.Contains(animal))
{
// etc...
}
Этот метод также будет работать с другими типами, кроме enums
, включая типы, которые вы не можете включить
. Это также полезно, если список допустимых значений будет известен только во время выполнения.
Обратите внимание, что если вы создаете новый список каждый раз, производительность будет снижаться.
Для этого можно использовать метод Extension:
public static bool IsAny<T>(this Enum value, params T[] values)
{
foreach (T e in values)
{
if (value.Equals(e)) return true;
}
return false;
}
usage:
enum TestEnum
{
Stackoverflow,
overflowStack,
stackstack
}
TestEnum val = TestEnum.overflowStack;
Console.WriteLine(val.IsAny(TestEnum.stackstack, TestEnum.Stackoverflow)); //false
Console.WriteLine(val.IsAny(TestEnum.overflowStack, TestEnum.Stackoverflow)); // true
Я мало что знаю о .NET 4.0 (на данный момент использую 3.5), но думаю, что нет никакого способа добиться эффекта, который нужен Pure.Krome.
Но приближение к этому виду сравнения может быть достигнуто с помощью массивов и методов расширения, предоставляемых LINQ.
Вот небольшой пример.
string foo = @"very weird";
if (new[] { @"don't do it", @"very weird" }.Contains(foo))
{
Console.WriteLine(@"bingo string");
}
int baa = 7;
if (new []{5, 7}.Contains(baa))
{
Console.WriteLine(@"bingo int");
}
Это выводит:
bingo string
bingo int
Этот способ потребляет больше ресурсов, чем простая цепочка сравнений и логических операторов, но обеспечивает синтаксис, аналогичный тому, который хочет получить Pure.Krome.
Если вы не хотите определять массивы с помощью new [] (это действительно некрасиво в логических условиях), вы можете сами определить для этого метод расширения.
public static class Extensions
{
public static bool IsOneOf<T>(this T obj, params T[] args)
{
return args.Contains(obj);
}
}
Итак, вы можете использовать этот метод расширения:
if (baa.IsOneOf(5, 7, 9, 10))
{
Console.WriteLine(@"bingo int");
}
Вывод действительно предсказуем, хех.
Еще один способ сделать это - разделить правила и логику, которая должна выполняться, когда любое / все из них истинны:
var animal_rules = new Func<Animal, bool>[]{
(a) => a == Animal.Cat,
(a) => a == Animal.Dog
};
var baa_rules = new Func<int, bool>[]{
(b) => b == 1,
(b) => b == 69
}
Затем вы можете использовать правило с помощью .Any () и / или All () для выполнения соответствующих операций, например:
if(animal_rules.Any(rule => rule(foo)){
// animal logic here...
}
if(baa_rules.Any(rule => rule(baa)){
// baa logic here...
}
HTH
Думаю, лучший вопрос - зачем вообще об этом беспокоиться? Это ясно как есть. Бьюсь об заклад, если бы вы разместили больше своего кода, в первую очередь нужно было бы решить многие другие вопросы.
Вы можете использовать переключатель
с провалом (уродливое наследие синтаксиса C):
switch (foo) {
case Animal.Cat:
case Animal.Dog:
{
...
break;
}
}
Однако будет работать только для таких тривиальных примеров, и я бы посоветовал придерживаться if
в любом случае.