2010-09-23 21 views
5

Soy bastante nuevo en C# procedente de Java, y me pregunto si hay una forma sencilla de evitar la repetición de códigos que implica tipos primitivos como esto:C# ¿Genéricos para evitar la repetición del código?


private Boolean AtLeastOneBufferItemIsNonZero(int[] Buffer) 
{ 
    Boolean result = false; 
    foreach (int Item in Buffer) 
    { 
     result = !(Item == (int)0); 
     if (result) break; 
    } 
    return result; 
} 

private Boolean AtLeastOneBufferItemIsNonZero(float[] Buffer) 
{ 
    Boolean result = false; 
    foreach (float Item in Buffer) 
    { 
     result = !(Item == (float)0); 
     if (result) break; 
    } 
    return result; 
} 

no puedo encontrar un supertipo "Número", por lo que puedo comparar "artículo" en una aplicación genéricos (no me importaría la penalización en el rendimiento del boxeo, aunque entiendo que en .NET no hay tal cosa?):


//SOMETHING LIKE THIS? 
private Boolean AtLeastOneBufferItemIsNonZero<T>(T[] Buffer) where T : NUMBERTYPE 
{ 
    Boolean result = false; 
    foreach (T Item in Buffer) 
    { 
     result = !(Item.Equals(0)); //Nope.... 
     if (result) break; 
    } 
    return result; 
} 

es la única manera de crear mi propia implementación de Number y tener un método compare()? Eso suena a excesivo ¿no?

+0

Hay algunas preguntas similares. Verifica si te ayudan. Un par de ejemplos: http://stackoverflow.com/questions/3329576/generic-constraint-to-match-numeric-types http://stackoverflow.com/questions/802024/struggling-to-come-up-with-a -generic-c-method-that-compare-different-types-of-n – Carlos

+0

En una nota al margen, use 'bool' en lugar de' Boolean'. bool es un atajo. – GenericTypeTea

Respuesta

13

LINQ que hace que este muy simple de hacer, al basarse en el hecho de que el valor por defecto de cualquier tipo numérico es igual a cero, y tienen métodos apropiados de igualdad:

private bool AtLeastOneBufferItemIsNonZero<T>(T[] items) 
{ 
    T zero = default(T); 
    EqualityComparer<T> comparer = EqualityComparer<T>.Default; 
    return items.Any(t => !comparer.Equals(t, zero)); 
} 

Ahora que no restringirlo a tipos numéricos, pero evita la repetición. Puede ir más lejos, generalizando a IEnumerable<T> y por lo que es un método de extensión:

public static class Extensions 
{ 
    public static bool ContainsNonDefaultValue<T>(this IEnumerable<T> source) 
    { 
     if (source == null) 
     { 
      throw new ArgumentNullException("source"); 
     } 
     T zero = default(T); 
     EqualityComparer<T> comparer = EqualityComparer<T>.Default; 
     return items.Any(t => !comparer.Equals(t, zero)); 
    } 
} 

Usted podría limitar este a tipos de valores, cambiando la restricción a

where T : struct 

pero eso sería una Poco inútil OMI. Con el cambio para usar EqualityComparer<T>.Default, puede también usar el método para verificar si algún valor en una secuencia de tipo de referencia no es nulo.

EDIT: Como nota al margen, otra forma de verlo es para revertir la condición:

return !items.All(t => comparer.Equals(t, zero)); 

Depende de si usted es feliz con el concepto de "cualquiera de ellos es distinto de cero" o "no son todos cero" :)

+0

¿Pero eso devuelve un valor que indica si al menos un elemento * es * cero? –

+0

@Fredrik: Doh, sí - arreglando ... –

+0

¿Pero no debería llamarse 'AtLeastOneBufferItemIsZero'? –

1
private Boolean AtLeastOneBufferItemIsNonZero<T>(T[] Buffer) 
{ 
    Boolean result = false; 
    foreach (T Item in Buffer) 
    { 
     result = !Item.Equals(default(T)); //Yep!!! 
     if (result) break; 
    } 
    return result; 
} 

PS. Use Linq

Cuestiones relacionadas