¿Hay otra manera de escribir algo como esto:C#. Hacer si (a == (b o c o d)). ¿Es posible?
if (a == x || a == y || a == z)
Una forma que encontré lo está haciendo de esta manera:
if(new [] {x,y,z}.Contains(a))
¿Hay otras buenas maneras?
¿Hay otra manera de escribir algo como esto:C#. Hacer si (a == (b o c o d)). ¿Es posible?
if (a == x || a == y || a == z)
Una forma que encontré lo está haciendo de esta manera:
if(new [] {x,y,z}.Contains(a))
¿Hay otras buenas maneras?
que a menudo utilizan un método de extensión que imita SQLS IN
:
public static bool IsIn<T>(this T obj, params T[] collection) {
return collection.Contains(obj);
}
De esa manera puedo hacer
if(a.IsIn(b, c, d)) { ... }
Cabe señalar que esto está haciendo exactamente lo mismo como en su segundo ejemplo, pero oculta el acto de organizarlo en una matriz y buscarlo fuera de la vista, de modo que queda con operaciones de lectura directa. –
¡Has sido demasiado rápido! (+1) –
@David Hedlund, ya noté que, simplemente estaba pensando que probablemente C# tiene algo para esto – Omu
Usted tiene la instrucción switch clásica:
switch(a) {
case x:
case y:
case z:
// Do stuff
break;
}
Agreeed; esta es, de lejos, la mejor manera de hacer esto (al menos, es el enfoque que yo uso). –
¿C# freak out si x, y, y z no son constantes? – cHao
@cHao, ¡eso no funcionaría bien! Siempre que esas variables tengan un valor afectado anteriormente, a se compara con los valores de memoria de x, y y z. – SiN
Sólo por diversión:
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);
}
}
pero realmente creo que la manera mejor es escribir el cheque llanura
if(a == x || a == y || a == z)
Como todo el mundo va a entender de inmediato lo que hace.
Fui por esta solución también (ver mi respuesta), aunque recomiendo encarecidamente que haga ese genérico, para evitar el boxeo/unboxing. la invocación seguirá siendo exactamente la misma, no tiene que especificar explícitamente el parámetro de tipo, ya que se deducirá del uso ... –
@David Hedlund: ¡buen punto! –
+1 no he visto este patrón de código ... :) – deostroll
if(a==x?true:a==y?true:a==z?true:false)
ooooh interesante, pero no tan legible como si (a == x || a == y || a == z)! – RYFN
Estoy tan en conflicto sobre cómo votar. – ChaosPandion
Por lo tanto, se desea reemplazar una sencilla construcción, el lenguaje eficiente que contiene optimizaciones de cortocircuito en algo mucho más lento que tiene el potencial para generar excepciones?
Sin embargo, si los elementos que desea comparar no son fijos en cantidad, es decir, en tiempo de ejecución podría ser t, u, v, w, x, y, z, etc ..., entonces la Colección. El método Contiene es la única opción, pero entonces estarás pasando objetos de colección en lugar de valores individuales, por lo que hay poca asignación de memoria.
Si tiene una gran cantidad de elementos para comparar 'a', pero los elementos no son dinámicos en tiempo de ejecución, entonces una instrucción de cambio podría ser una mejor opción.
'HashSet
¿Por qué necesitarías otra manera? Dado que no es una cuestión de funcionalidad, creo que el objetivo es mejorar la legibilidad. Si tiene algunas variables con nombres significativos, sería más legible simplemente comparar utilizando ==
. Si tiene más, puede usar Contains
contra una lista como en su otra muestra. embargo, otra forma sería comparar contra las banderas de enumeración:
[Flags]
public enum Size
{
Small = 1,
Medium = 2,
Large = 4
}
Y entonces de saber si mySize
está en Small
o Medium
:
selectedSizes = Size.Small | Size.Medium;
mySize = Size.Small;
if (mySize & selectedSizes)
{
...
}
probar este
var res2 = new[] { 1, 2, 3 }.Any(x => x == 2);
Su solución a reescribirlo como
if(new [] {x,y,z}.Contains(a))
no es un buen movimiento.
Tiene una operación lógica simple y eficiente, que todo programador entiende fácilmente y que contiene lógica de cortocircuito para acelerarla y, en su lugar, ha producido código que requiere un momento para comprender y que es considerablemente menos eficiente.
¡A veces tus colegas ingenieros lo preferirán si no tratas de ser "inteligente"!
Estoy de acuerdo en que sería más lento, pero 'Contiene' todavía cortocircuitaría. Bueno, al menos cualquier implementación razonable sería eso. –
@Brian Gideon: 'Contains' se cortocircuitará, por lo que no continuará con las comparaciones si ya se encuentra una coincidencia, pero antes de que' Contains' pueda comenzar, debe inicializar la matriz, y está en ese punto que accedes a 'x',' y' y 'z'. si 'z' requiere un gran cálculo para evaluar, y' a == x', 'z' todavía se evaluará antes de que la operación' Contains' se inicie. –
@David: Muy buen punto. –
Por ejemplo, su lógica es así:
if(a==x || a== y|| a==z)
{
DoSomething();
}
else
{
DoOtherThings();
}
voluntad equivalente a:
if(a!=x&& a != y && a!= z)
{
DoOtherThings();
}
else
{
DoSomething();
}
Saludos.
:) ese no era el punto, hiciste lo mismo pero solo en una forma diferente, tenías que escribir "a" una sola vez – Omu
¡Lo entendí mal! –
Consideremos un caso en el que un == x, y y y z son de lenta a evaluar, funciones caros.
if(a == x || a == y || a == z)
que tienen el beneficio de la de cortocircuito ||
-operator, por lo que y y z no será evaluado.new[] { x, y, z }
- y y z será evaluado cada vez que .El 'truco' con .Contains()
sería más útil si había una sintaxis elegante para crear secuencia-lazy evaluado (IEnumerable<T>
). es decir, algo así como yield return x; yield return y;...
, pero en línea y más corto.
¿Por qué lo quiere de otras maneras? Solo tengo curiosidad –
@despart - Tiene un poco más de sentido con los nombres descriptivos de las variables, pero en cualquier caso seguiría usando los operadores lógicos. – ChaosPandion
Probablemente causa que crear una matriz solo para comparar más de dos números sea un error. – cHao