2012-04-03 19 views
9

¿Por qué esta afirmación falla?¿Por qué esta comparación de color falla?

Assert.AreEqual(Color.Red, Color.FromArgb(Color.Red.A, Color.Red.R, Color.Red.G, Color.Red.B)); 
+4

hacer esto: Color.Red.ToArgb() == color. FromArgb (255, 0, 0) .ToArgb() – BlueVoodoo

+0

Vea aquí http://stackoverflow.com/questions/7464994/how-to-compare-a-color-by-the-getpixel-method-and-a-color -passed-in-a-method-lik – nawfal

Respuesta

11

Aquí es cómo implementar la comparación Colores:

public override bool Equals(object obj) 
{ 
    if (obj is Color) 
    { 
     Color color = (Color) obj; 
     if ((this.value == color.value) 
      && (this.state == color.state) 
      && (this.knownColor == color.knownColor)) 
     { 
      return ((this.name == color.name) 
       || ((this.name != null) 
        && (color.name != null) 
        && this.name.Equals(color.name))); 
     } 
    } 
    return false; 
} 

Cómo funciona:

  1. campo value comparación. Son los valores Argb de la instancia actual (están almacenados en un campo del tipo long). Entonces, si Argb es diferente, tenemos diferentes colores. Usted pasa este paso exitosamente.
  2. Campo state comparado. Muestra la forma en que se creó el color: de Argb, de KnownColor o por nombre. En realidad, su comparación falla en este paso.
  3. Campo knownColor comparó. Tiene valor de KnownColor enum, o cero, si el color no se creó a partir de un color conocido.
  4. Campo name comparado. Tiene el valor null para todos los colores, excepto los creados por nombre.

lo tanto, si desea comparar los valores de los colores, se debe utilizar value campo en comparación (que es devuelto por el método ToArgb):

Assert.AreEqual(color1.ToArgb(), color2.ToArgb()); 

Editar

Para crear una copia de algún color puede usar el siguiente método de extensión:

public static class ColorHelper 
{ 
    public static Color Copy(this Color color) 
    { 
     if (color.IsKnownColor) 
      return Color.FromKnownColor(color.ToKnownColor()); 

     if (color.IsNamedColor) 
      return Color.FromName(color.Name); 

     // this is better, then pass A,r,g,b separately 
     return Color.FromArgb(color.ToArgb()); 
    } 

Ahora pasa afirmación:

Assert.AreEqual(Color.Red, Color.Red.Copy()); 

Pero no tiene sentido, porque se puede utilizar instancia de un solo color en cada lugar de su programa :)

2

Color.Red es un color con nombre, mientras que Color.FromArgb(...) no lo es. Por lo tanto, no se consideran iguales, aunque tengan los mismos valores ARGB. Tenga en cuenta que la representación de cadena también es diferente:

Color.Red.ToString()   : "Color [Red]" 
Color.FromArgb(...).ToString() : "Color [A=255, R=255, G=0, B=0]" 
2

El Equals anulación de las Color clase comprueba, si los dos colores se nombran (conocido) colores o no:

public override bool Equals(object obj) 
{ 
    if (obj is Color) 
    { 
     Color color = (Color) obj; 
     if (((this.value == color.value) && (this.state == color.state)) && (this.knownColor == color.knownColor)) 
     { 
      return ((this.name == color.name) || (((this.name != null) && (color.name != null)) && this.name.Equals(this.name))); 
     } 
    } 
    return false; 
} 
2

ya que el color es una estructura, tiene muchas propiedades además de los valores ARGB. Por ejemplo, si crea un color usando dos enfoques diferentes, tendrá diferentes nombres; por lo tanto, no serán iguales.

 Color a = Color.Red;    
     Color b = Color.FromArgb(a.A, a.R, a.G, a.B); 

     string name1 = a.Name; //name is Red 
     string name2 = b.Name; //name is ffff0000 

Las estructuras no tienen ninguna lógica de la igualdad por sí mismos (es decir., Si desea utilizar '=='). Así, para cada estructura, se definirá este operador. Si investigas Color, verás la siguiente definición del operador '=='. Depende de cómo se implemente este operador.

// Summary: 
    //  Tests whether two specified System.Drawing.Color structures are equivalent. 
    // 
    // Parameters: 
    // left: 
    //  The System.Drawing.Color that is to the left of the equality operator. 
    // 
    // right: 
    //  The System.Drawing.Color that is to the right of the equality operator. 
    // 
    // Returns: 
    //  true if the two System.Drawing.Color structures are equal; otherwise, false. 
    public static bool operator ==(Color left, Color right); 

También 'es igual a' es anulado en el struct tal que verifica la equivalencia de estructuras;

// Summary: 
    //  Tests whether the specified object is a System.Drawing.Color structure and 
    //  is equivalent to this System.Drawing.Color structure. 
    // 
    // Parameters: 
    // obj: 
    //  The object to test. 
    // 
    // Returns: 
    //  true if obj is a System.Drawing.Color structure equivalent to this System.Drawing.Color 
    //  structure; otherwise, false. 
    public override bool Equals(object obj); 
+0

No es cierto. En el caso de 'Color b = Color.FromArgb (a.A, a.R, a.G, a.B);' nombre será 'null'. –

+0

@lazyberezovsky has probado esto? Lo he intentado y se comporta de la forma indicada en la respuesta. – daryal

+0

La propiedad 'Name' solo genera cadena si no hay ninguna realmente. Señalé esto, porque la propiedad 'Nombre' no se usa en comparación. Solo se utiliza el 'nombre' del campo real. –

2

Esto es una consecuencia de la forma en que se implementa la estructura System.Drawing.Color. Tiene una propiedad Name separada, que es "Roja" para Color.Red pero es diferente cuando crea su propio Color de Color.Red. System.Windows.Media.Color (es decir, la implementación de WPF Color) no presenta el mismo problema.

Cuestiones relacionadas