C#: ¿La forma más elegante de probar si int x es un elemento de un conjunto dado?


Problema: Prueba si x ∉ { 2, 3, 61, 71 }

A menudo me preguntaba si no hay una mejor manera que:

if (x != 2 && x != 3 && x != 61 && x != 71)
{
  // do things
}

Y

if (!new List<int>{ 2, 3, 61, 71 }.Contains(x))
{
  // do things
}

Este último parece bastante elegante, pero en realidad es un poco irritante si lo lees, especialmente debido a la inversión. Es algo feo porque en inglés decimos "x no es un elemento de ...", que es difícil de expresar en C# sin irritar la sobrecarga. Tal vez uno podría decir if (Object(x).IsElementOf(new[] { ... })) o así?

Hmm.. alguna sugerencia? Ser ¿hay algún método estándar. Net para probar cosas así?

Author: Lasse Vågsæther Karlsen, 2011-11-22

6 answers

Uso un método de extensión:

using System.Linq;

...

public static bool In<T>(this T item, params T[] list)
{
    return list.Contains(item);
}

...


if (!x.In(2,3,61,71))
...

Puede cambiarle el nombre a IsElementOf si prefiere este nombre...

 42
Author: Thomas Levesque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-22 15:14:59

Vieja pregunta, pero no he visto esta respuesta simple:

!new []{2, 3, 61, 71}.Contains(x)
 6
Author: BlackTigerX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-19 20:25:03

Puedes usar el siguiente método LinQ:

var list = new List<int> { 1, 2, 3, 4, 5 };
var number = 3;

if (list.Any(item => item == number))
    //number is in the list

Y para la legibilidad se puede poner en un método de extensión:

public static bool IsElementOf(this int n, IEnumerable<int> list)
{
    return list.Any(i => n == i);
}

//usage
if(3.IsElementOf(list)) //in the list
 5
Author: Abbas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-22 15:11:42

¿Qué pasa con

if(new[] { 2, 3, 61, 71 }.Except(x).FirstOrDefault() != 0)
{
   ...
}

O algo en esas líneas?

 1
Author: John,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-22 15:41:43
var list=CreateNewList(); //returns your list of elements
var element=GetElement(); //returns an element that might be in the list
if(list.Any(x=>x.Equals(element))
{
  //do something
}

Todavía está invertido de lo que estás acostumbrado, pero es más expresivo (si la lista tiene algún valor que sea igual a elemento).

 0
Author: Michael Brown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-22 15:06:15

Asumiendo que se refiere a && y no ||, puede escribir un func y usarlo a lo largo de su código. Puede acortar la nueva parte [] ya que el tipo (int) es inferido por el parámetro in del func.

Func<int, bool> IsSafe = x => !new[] { 2, 3, 61, 71 }.Contains(x);

Console.WriteLine(IsSafe(68)); // is true
Console.WriteLine(IsSafe(2));  // is false
 0
Author: aevanko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-22 15:46:47