c# - extensions - extension method must be defined in a non-generic static class
¿Es esto un buen uso de un ExtensionMethod? (8)
¿Realmente tiene la intención de contener y garantiza 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, para decir que el valor es realmente el mismo objeto que value1, 2, 3 o 4, dado que V es el objeto tipo 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 de mano corta:
if (new List<V>{value, value2, value3, value4 }.Any( v => v==value))
// do something
No pude hacer que las expresiones lambda anteriores funcionen en un método de extensión genérico.
Como un buen ejemplo (aunque irrelevante) de lo que creo que es una sintaxis encantadora y legible, el modismo en Python sería
if value in (value1, value2, value3, value4):
Acabo de escribir una declaración if en las líneas de
if (value == value1 || value == value2 || value == value3 || value == value4)
//do something
y me molesta que siempre tenga que repetir la parte ''valor ==''. En mi opinión, esto no tiene otra finalidad que no sea dificultar la lectura.
Escribí el siguiente ExtensionMethod que debería hacer que el escenario anterior sea más legible:
public static bool IsEqualToAny<T>(this T value, params T[] objects)
{
return objects.Contains(value);
}
Ahora puedo simplemente escribir
if (value.IsEqualToAny(value1, value2, value3, value4))
//do something
¿Es este un buen uso de un ExtensionMethod?
EDITAR:
Gracias por todas las excelentes respuestas. Para el registro: he guardado el método. Si bien la sugerencia de que podría simplemente usar new []{value1,value2,value3,value4}.Contains(value)
es verdadera, 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í.
Es inusual escribir un método de extensión para una T
sin restricción. 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 esto como un método de extensión ; tal vez solo use un método estándar de utilidad estática.
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
Haría 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í, iría 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.
Me parece bien, aunque parece un poco poco convencional.
No ha agregado la funcionalidad que solo es útil para una aplicación o contexto específico, su extensión está claramente nombrada y el comportamiento es obvio sin tener que mirar la implementación.
La respuesta es "Sí, lo es"
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.
También puede usar la sintaxis del método LINQ para esa tarea (mediante el uso del espacio de nombres System.Linq):
object[] objects = new object[10];
objects.Contains(new MyClass());
Hmm, déjame pensar un momento ... Oh, ya lo estás usando. Pero lo has puesto en un método diferente en lugar de llamarlo directamente.
Si solo está revisando un valor de Enum (como dijo en el comentario de 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 otra manera; si es un dominio específico, agréguelo a su lógica comercial. Si es genérico, crea una clase de ayuda.