Является ли эта сложная вещь равной этому? или это? или это?
Скажем, я работаю с объектом класса thing
. То, как я получаю этот объект, немного многословно:
BigObjectThing.Uncle.PreferredInputStream.NthRelative(5)
Я хотел бы видеть, равен ли этот thing
x
или y
или z
. Наивный способ написать это может быть:
BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == x ||
BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == y ||
BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == z
В некоторых языках я мог бы написать что-то вроде этого:
BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == x |= y |= z
но С# не позволяет этого.
Существует ли С# -идиоматический способ записи этого теста в виде одного выражения?
Ответы
Ответ 1
Просто используйте переменную:
var relative = BigObjectThing.Uncle.PreferredInputStream.NthRelative(5);
return relative == x || relative == y || relative == z;
Или, если вы хотите получить представление о большом наборе вещей:
var relatives = new HashSet<thing>(new[] { x, y, z });
return relatives.Contains(BigObjectThing.Uncle.PreferredInputStream.NthRelative(5));
Ответ 2
Метод расширения будет имитировать это:
public static bool EqualsAny(this Thing thing, params object[] compare)
{
return compare.Contains(thing);
}
bool result = BigObjectThing.Uncle.PreferredInputStream.NthRelative(5).EqualsAny(x, y, z);
С# не имеет синтаксиса по умолчанию для такого OR-подобного сравнения afaik.
Ответ 3
Как указывали другие, коллекция является одним из способов сделать это. Если вы хотели бы иметь немного больше гибкости, чем использовать Contains
(который действительно позволяет протестировать x.Equals(y)
) и даже поддерживать привязку &=
в дополнении к |=
, я бы предложил Any
или All
методы расширения, встроенные в .NET.
var compares = new[] { x, y, z };
var relative = BigObjectThing.Uncle.PreferredInputStream.NthRelative(5);
// Simulate |= behavior
return compares.Any(x => relative == x);
// Simulate &= behavior
return compares.All(x => relative == x);
// A more complex test chained by OR
return compares.Any(x => relative.SomeProperty == x.SomeProperty);
// A less readable but one-line approach
return (new [] {x, y, x}).Any(x => BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == x);
Ответ 4
Сначала вы можете поместить свои объекты в Collection
, а затем использовать Contains()
.
var relatives = new Collection<Thing> { x, y, z };
if (relatives.Contains(BigObjectThing.Uncle.PreferredInputStream.NthRelative(5)))
{
...
}
Это может быть сокращено еще больше (для удобства чтения):
if (new Collection<Thing> { x, y, z }.Contains(BigObjectThing.Uncle.PreferredInputStream.NthRelative(5)))
{
...
}
Ответ 5
Есть ли такой материал в одном выражении? Это требует моего безумного умения LINQ!
Рабочий образец (http://ideone.com/VNTFnz):
using System.Linq;
public class Test
{
static int getStuff()
{
return 1;
}
public static void Main()
{
if ((from option in new int[] {1, 2, 3}
let thing = getStuff()
where option == thing
select option).Any())
System.Console.WriteLine("in the list!");
}
}
В переводе на ваш случай это будет примерно так:
if ((from option in new Thing[] {x, y, z}
let thing = BigObjectThing.Uncle.PreferredInputStream.NthRelative(5)
where option == thing
select option).Any())
System.Console.WriteLine("in the list!");
Я не говорю, что вы должны делать это таким образом, но эй, вы получите логический результат, вы можете проверить любое количество значений вместо x
, y
и z
! Кроме того, это не ограничивает вас сравнением с ==
, вы можете использовать все, что вам нравится на своем месте.
И эй, одно выражение!
Шутки в сторону, придумывая странные способы делать то, что вы хотели сделать, это весело, но вы действительно должны поместить результат BigObjectThing.Uncle.PreferredInputStream.NthRelative(5)
в переменную!