2012-04-03 2 views
9

Почему это утверждение терпит неудачу?Почему это сравнение цветов не удается?

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

это сделать: Color.Red.ToArgb() == Color. FromArgb (255, 0, 0) .ToArgb() – BlueVoodoo

+0

См. Здесь http://stackoverflow.com/questions/7464994/how-to-compare-a-color-by-the-getpixel-method-and-a-color -passed-in-a-method-lik – nawfal

ответ

11

Вот как реализовано сравнение Цвета:

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; 
} 

Как это работает:

  1. поле value сравниваться. Это значения Argb текущего экземпляра (они хранятся в одном поле типа long). Итак, если у Argb разные, у нас разные цвета. Вы успешно пройдете этот шаг.
  2. Поле state по сравнению. Он показывает способ создания цвета: от Argb, от KnownColor или по имени. На самом деле ваше сравнение не выполняется на этом шаге.
  3. Поле knownColor по сравнению. Он имеет значение перечисления KnownColor, или ноль, если цвет не был создан из известного цвета.
  4. Поле name по сравнению. Он имеет значение null для всех цветов, кроме созданных по имени.

Так что, если вы хотите сравнить значения цветов, вы должны использовать value поле сравнения (он возвращается методом ToArgb):

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

Редактировать

Чтобы создать копию определенного цвета, вы можете использовать следующий способ расширения:

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()); 
    } 

Теперь утверждение проходит:

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

Но это не имеет никакого смысла, потому что вы можете использовать один экземпляр цвета в любом месте вашей программы :)

2

Color.Red именованный цвет, в то время как Color.FromArgb(...) нет. Поэтому они не считаются равными, хотя они имеют одинаковые значения ARGB. Обратите внимание, что строковое представление также отличается:

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

Equals переопределения Color проверки класса, будут ли названы оба цвета (известный) цвет или нет:

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

Поскольку цвет является структурой, он обладает многими свойствами, отличными от значений ARGB. Например, если вы создаете цвет, используя два разных подхода, они будут иметь разные имена; таким образом, они не будут равны.

 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 

Структуры не имеют никакой логики равенства сами по себе (то есть., Если вы хотите использовать «==»). Таким образом, для каждой структуры, этот оператор должен быть определен. Если вы исследуете Color, вы увидите следующее определение оператора '=='. Это зависит от того, как этот оператор реализован.

// 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); 

Кроме «Равно» является переопределен в структуры таким образом, что он проверяет эквивалентность структур;

// 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

Неправда. В случае 'Color b = Color.FromArgb (a.A, a.R, a.G, a.B);' name будет 'null'. –

+0

@ lazyberezovsky вы пробовали это? Я пробовал, и он ведет себя так, как говорится в ответе. – daryal

+0

Свойство 'Name' просто генерирует строку, если ее нет. Я указал на это, потому что свойство 'Name' не используется для сравнения. Используется только фактическое поле 'name'. –

2

Это является следствием реализации структуры System.Drawing.Color. Он имеет отдельное свойство Name, которое является «красным» для Color.Red, но отличается, когда вы создаете свой собственный Color от Color.Red. System.Windows.Media.Color (т.е. реализация WPF Color) не проявляет этой же проблемы.

Смежные вопросы