2009-02-11 21 views
10

acabo de escribieron una sentencia if en las líneas de¿Es este un buen uso de un ExtensionMethod?

if (value == value1 || value == value2 || value == value3 || value == value4) 
    //do something 

y me molesta que siempre tengo que repetir el 'valor ==' parte. En mi opinión, esto no tiene otra finalidad que no sea dificultar la lectura.

me escribió lo siguiente ExtensionMethod que debería hacer más legible escenario anterior:

public static bool IsEqualToAny<T>(this T value, params T[] objects) 
{ 
    return objects.Contains(value); 
} 

Ahora simplemente hay que escribir

if (value.IsEqualToAny(value1, value2, value3, value4)) 
    //do something 

Es este un buen uso de un ExtensionMethod?

EDIT:

Gracias por todas las grandes respuestas. Para el registro: he guardado el método. Si bien la idea de que usted podría simplemente utilizar new []{value1,value2,value3,value4}.Contains(value) es cierto, simplemente prefiero leer este tipo de instrucción if de izquierda a derecha (si este valor es igual a cualquiera de estos en lugar de si estos valores contienen este valor). Tener un método más que aparezca en intellisense en cada objeto no es un problema para mí.

Respuesta

4

No ha agregado la funcionalidad que solo es útil para una aplicación o contexto específico, su extensión se nombra claramente y el comportamiento es obvio sin tener que mirar la implementación.

la respuesta es "Sí, es"

1

Me parece bien, aunque parece un poco poco convencional.

1

Parece bastante justo, pero daría un paso atrás. ¿Puedes poner algún significado comercial en la comparación? ¿Cuáles son esos valores? Tal vez sería mejor con un método llamado IsSpecialCustomerLocation o algo que exprese la intención real del código.

+0

gracias. Es bastante genérico. Solo estaba comparando un valor de enumeración: estaba relacionado con la programación de la GUI, por lo que no tenía ningún significado comercial como tal. –

1

También puede utilizar la sintaxis método de LINQ para esa tarea (mediante el uso de espacio de nombres System.Linq):

  object[] objects = new object[10]; 
     objects.Contains(new MyClass()); 

Mmm déjame pensar un momento ... Oh, ya lo utilizan. Pero lo has puesto en un método diferente en lugar de llamarlo directamente.

+0

Eso es demasiado trabajo para hacer cada vez. –

+0

la sintaxis del inicializador de matriz sería aún más limpia ... ver mi publicación. –

+0

Tienes razón. ¡De acuerdo! – Alexander

5

Es inusual para escribir un método de extensión para un T sin restricciones. No menos importante, este enfoque rápidamente hará que su intellisense sea bastante difícil de usar.

Si bien es válido, probablemente evitaría este como un método de extensión - quizás solo use un método de utilidad estático estándar.

La sintaxis del inicializador de matriz C# 3 podría ser más fácil?

bool isTrue = new[] { 1, 2, 3 }.Contains(3); 

Por supuesto, para grandes conjuntos de datos, es posible que desee almacenar en caché un HashSet<T> algún lugar ;-P

+0

gracias por el comentario Marc. ¿podría explicar por qué esto hará que intellisense sea difícil de usar? –

+0

Porque aparecerá en cada variable cuando presiona ".". Solo se necesita un puñado de estos métodos para empezar a dificultar la búsqueda de métodos relevantes para un tipo ... en realidad, no vas a querer utilizar este método ** que ** a menudo (espero) en comparación con cualquier otro método disponible. –

+0

Veo - buen punto. Gracias. –

1

Me gustaría hacer una clase estática para ese propósito.No me gusta esa solución porque agrega un método a todas las clases que parece un poco exagerado. Sin embargo, de alguna manera funciona con OOD porque le pides a los objetos que realicen funciones sobre ellos mismos (un poco).

Aún así, me gustaría ir con una clase reutilizable en su lugar porque puedo ver cómo se podría formar un antipatrón. No lo llamo antipatrón aún, pero si aparecen demasiados de esos constructos, lo llamaría un antipattern de legibilidad ya que cada objeto se llenaría de métodos de extensión. Lo veo como contaminación del espacio de nombres, pero como contaminación de los miembros de la clase.

if (ConditionHelper.IsEqualToAny(value, value1, value2, value3)) 
{ 
    // Do something 
} 

Hace el mismo trabajo y no contamina nada.

+0

Ahora que lo pienso, adolece de un pequeño problema de legibilidad.Tiene que ver con que no es obvio que el valor se verifique contra value1, value2, value3 y demás. value.IsEqualToAny (value1, value2, value3) tiene una mejor legibilidad. Mi preocupación era solo por contaminar a los miembros. – Statement

1

¿Realmente tiene la intención de Contener y garantizar que va a aplicar Contiene en todos los objetos posibles donde podría usar este método de extensión?

Si algunos objetos determinados prueban la igualdad al sobrecargar al operador ==, la solución genérica fallará. Eso hace que no sea un verdadero equivalente de las múltiples == pruebas. ¡También es un buen ejemplo del peligro de escribir métodos de extensión!

El siguiente código Linq funciona cuando implementa la sobrecarga del operador, así como si está utilizando el significado predeterminado == de comparar referencias de objetos, decir que el valor es realmente el mismo objeto que value1, 2, 3 o 4, dado V como el tipo de objeto de sus valores en este caso particular:

V[] lv = { value, value2, value3, value4 }; 
if (lv.Any(v => v==value)) 
    // do something 

o una versión corta a mano:

if (new List<V>{value, value2, value3, value4 }.Any(v => v==value)) 
    // do something 

no pude conseguir las expresiones lambda anteriores para trabajar en un método de extensión genérica .

Como buen (si es pertinente) ejemplo de lo que creo que es una sintaxis preciosa, fácil de leer, el idioma en Python sería

if value in (value1, value2, value3, value4): 
+0

No veo cómo esto es un problema. El método Contiene (que es un Método de extensión (implementado en System.Linq.Enumerable)) utiliza un EqualityComparer que (en el caso predeterminado) usa una comparación ==. –

+0

Tal vez lo implementé incorrectamente o hay algo sobre la forma en que está vinculado, pero cuando lo pruebo el método de extensión no puede detectar un objeto que es un objeto diferente pero igual en función de su operador == sobrecarga. –

0

Si sólo está mirando un valor de enumeración (como bien dice en el comente sobre la respuesta de Rogers), debe usar un FlagsAttribute en el Enum.

[Flags] 
public enum Value 
{ 
    Value1 = 0, 
    Value2 = 1, 
    Value3 = 2, 
    Value4 = 4 
} 

Value value = Value.Value1; 
if (value | Value.Value1 | Value.Value2 | Value.Value3 | Value.Value4) 
{ 
    // You can also use other bitwise operations, like & (AND),^(XOR) and ~ (NOT) 
} 

De lo contrario; si es un dominio específico, agréguelo a su lógica comercial. Si es genérico, crea una clase de ayuda.

+0

No creo que sea apropiado. Solo porque quiero verificar un número de valores diferentes no significa que la enumeración debe ser un campo de bit. No quiero que el valor enum sea un valor combinado. - gracias por tu aporte sin embargo. He estado usando este método de extensión desde hace un tiempo y ha sido bastante útil en varias situaciones. –

Cuestiones relacionadas