2010-07-14 2 views
26

Есть еще один способ, чтобы написать что-то вроде этого:C#. Сделайте, если (a == (b или c или d)). Является ли это возможным?

if (a == x || a == y || a == z) 

Один из способов, который я нашел делает это так:

if(new [] {x,y,z}.Contains(a)) 

Есть ли другие хорошие способы?

+2

Почему вы хотите это другими способами? Мне просто любопытно –

+0

@despart - Это имеет немного больше смысла с описательными именами переменных, но в любом случае я все равно буду использовать логические операторы. – ChaosPandion

+0

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

ответ

63

Я часто использую метод расширения, который имитирует SQLs IN:

public static bool IsIn<T>(this T obj, params T[] collection) { 
    return collection.Contains(obj); 
} 

Таким образом я могу сделать

if(a.IsIn(b, c, d)) { ... } 
+2

Следует отметить, что это делает то же самое как и в вашем втором примере, но он замалчивает акт расположения его в массиве и ищет его вне поля зрения, так что вы остаетесь с легко читаемыми операциями. –

+2

Вы слишком быстро! (+1) –

+0

@ Давид Хедлунд, я заметил это, я просто думал, что, возможно, у C# есть что-то для этого – Omu

10

У вас есть классический заявление переключатель:

switch(a) { 
    case x: 
    case y: 
    case z: 
     // Do stuff 
     break; 
} 
+0

Согласен; это, безусловно, лучший способ сделать это (по крайней мере, это подход, который я принимаю). –

+2

Будет ли C# freak out, если x, y и z не являются константами? – cHao

+0

@ cHao, нет, это сработает! Пока эти переменные имеют ранее сказанное значение, a сравнивается с значениями памяти x, y и z. – SiN

6

Только для fun:

using System; 

static class Program { 

    static bool In(this object obj, params object[] values) { 
     foreach (object value in values) { 
      if (obj.Equals(value)) { 
       return true; 
      } 
     } 
     return false; 
    } 

    static void Main(string[] args) { 
     bool test1 = 3.In(1, 2, 3); 
     bool test2 = 5.In(1, 2, 3); 
    } 
} 

Но я действительно думаю, что лучший способ писать равнину Регулярно проверяйте

if(a == x || a == y || a == z) 

Как все поймут сразу, что он делает.

+0

Я тоже пошел на это решение (см. Мой ответ), хотя я настоятельно рекомендую вам сделать это общее, чтобы избежать бокса/распаковки. вызов будет по-прежнему точно таким же, вам не нужно явно указывать параметр типа, поскольку он будет выведен из использования ... –

+0

@David Hedlund: хорошая точка! –

+0

+1 не видел этот код кода ... :) – deostroll

1
if(a==x?true:a==y?true:a==z?true:false) 
+1

ooooh интересный, но нигде рядом не читаемый, как если бы (a == x || a == y || a == z)! – RYFN

+7

Я так не согласен с тем, как голосовать. – ChaosPandion

3

Итак, вы хотите, чтобы заменить простую, сверхвысокую конструкцию языка, который содержит короткое замыкание оптимизаций в нечто гораздо медленнее, что имеет потенциал для метания исключения?

Однако, если элементы, которые вы хотите сравнить, не фиксированы в количестве, то есть во время выполнения это могут быть t, u, v, w, x, y, z и т. Д., Затем коллекция. Содержит метод - единственный вариант, но тогда вы будете передавать объекты коллекции, а не отдельные значения, и поэтому есть небольшое количество ресурсов памяти ovrehead.

Если у вас есть большое количество элементов для сравнения «a», но элементы не динамичны во время выполнения, тогда оператор switch лучше подходит.

+0

'HashSet ' - это то, что мне нравится использовать при работе с динамическим количеством сравнений. – ChaosPandion

2

Зачем вам нужен еще один способ? Поскольку это не вопрос функциональности, я бы предположил, что дело в улучшении читаемости. Если у вас есть несколько переменных со значимыми именами, было бы более удобно читать, используя ==. Если у вас есть больше, вы можете использовать Contains против списка, как в вашем другом примере. Еще один способ будет сравнение с перечислений флагов:

[Flags] 
public enum Size 
{ 
    Small = 1, 
    Medium = 2, 
    Large = 4 
} 

А затем выяснить, если mySize в Small или Medium:

selectedSizes = Size.Small | Size.Medium; 
mySize = Size.Small; 
if (mySize & selectedSizes) 
{ 
    ... 
} 
5

Ваше решение перепишите его как

if(new [] {x,y,z}.Contains(a)) 

не является хорошим ходом.

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

Иногда ваши коллеги-инженеры предпочитают это, если вы не пытаетесь быть «умными»!

+0

Я согласен с тем, что это будет медленнее, но «Содержит» все еще будет замыкаться. Ну, по крайней мере, любая разумная реализация. –

+0

@Brian Gideon: «Содержит» будет коротким, конечно, поэтому он не продолжит сравнения, если совпадение уже найдено, но прежде чем «Содержит» может начаться, вам нужно инициализировать массив, и он находится в что вы получаете доступ к 'x',' y' и 'z'. если 'z' требует вычисления больших вычислений, а' a == x', 'z' будет по-прежнему оцениваться до того, как операция' Contains' будет запущена. –

+0

@ Давид: Очень хорошая точка. –

0

Например, логика такова:

if(a==x || a== y|| a==z) 
{ 
    DoSomething(); 
} 
else 
{ 
    DoOtherThings(); 
} 

будет эквивалентно:

if(a!=x&& a != y && a!= z) 
{ 
    DoOtherThings(); 
} 
else 
{ 
    DoSomething(); 
} 

Приветствия.

+1

:) Это было не главное, вы сделали то же самое, но только в другой форме, вам нужно было написать «a» только один раз – Omu

+0

Непонятно! –

5

Рассмотрим случай, когда == х и у и г медленно к оценке, дорогих функций.

  • В if(a == x || a == y || a == z) у вас есть преимущество короткого замыкания || -оператора, так что вы у и г не будет оцениваться.
  • Если вы сделаете массив с new[] { x, y, z } - у и г будет оценен каждый раз.

Основной хитрость с .Contains() был бы более полезным, если был элегантный синтаксис для создания ленивой-оценивали последовательности (IEnumerable<T>). то есть что-то вроде yield return x; yield return y;..., но вложенное и короче.

Смежные вопросы