Можно ли реорганизовать этот оператор C # if (..)? - PullRequest
7 голосов
/ 03 апреля 2010

простой вопрос: -

У меня есть следующие простые операторы if (..): -

if (foo == Animal.Cat || foo == Animal.Dog)
{ .. }

if (baa == 1|| baa == 69)
{ .. }

возможно ли их преобразовать в нечто вроде ...

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я знаю, что это не компилируется ... но это то, что я пытаюсь получить ...

if (foo == (Animal.Cat || Animal.Dog))
{ .. }

if (baa == (1 || 69))
{ .. }

Приветствия:)

EDIT

Интересно, может ли расширение лямбда-выражения сделать это? : P

Ответы [ 7 ]

13 голосов
/ 03 апреля 2010

Обычно я создаю метод расширения с именем IsIn(), который принимает универсальный массив параметров типа <T> и затем вызывает .Contains(), передавая экземпляр, для которого вызывается расширение.

Похоже, if (foo.IsIn(foo1, foo2)). Очень прост в написании, супер прост в использовании.

3 голосов
/ 03 апреля 2010

Это не очень полезно в этом конкретном случае, когда у вас есть только два варианта, но если их может быть много, вы можете поместить их в список, а затем использовать Contains, например:

List<Animal> allowedAnimals = new List<Animal>
{
    Animal.Cat,
    Animal.Dog,
    Animal.Fish,
    Animal.Frog,
    Animal.Horse
};

if (allowedAnimals.Contains(animal))
{
    // etc...
}

Этот метод также будет работать с другими типами, кроме enums, включая типы, которые нельзя switch использовать. Это также полезно, если список разрешенных значений будет известен только во время выполнения.

Обратите внимание, что если вы создаете новый список каждый раз, это приведет к снижению производительности.

2 голосов
/ 03 апреля 2010

Для этого вы можете использовать метод 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;
        }

использование:

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
1 голос
/ 03 апреля 2010

Я не особо разбираюсь в .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");
}

Вывод действительно предсказуемый, хе.

1 голос
/ 03 апреля 2010

Вы можете использовать switch с падением (уродливое наследие синтаксиса C):

switch (foo) {
    case Animal.Cat:
    case Animal.Dog:
    {
        ...
        break;
    }
}

Впрочем, будет работать только для таких тривиальных примеров, и в любом случае я бы рекомендовал придерживаться if.

0 голосов
/ 03 апреля 2010

Я думаю, что лучший вопрос - зачем вообще беспокоиться об этом? Это ясно, как оно есть. Бьюсь об заклад, если бы вы опубликовали больше своего кода, было бы много других вопросов, которые следует рассмотреть в первую очередь.

0 голосов
/ 03 апреля 2010

Еще один способ сделать это - отделить правила и логику, которую необходимо выполнить, когда какой-либо из них / все они верны:

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...
}

НТН

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...