Почему это сравнение цветов не удается? - PullRequest
9 голосов
/ 03 апреля 2012

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

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

Ответы [ 5 ]

11 голосов
/ 03 апреля 2012

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

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 голосов
/ 03 апреля 2012

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

2 голосов
/ 03 апреля 2012

Переопределение 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 голосов
/ 03 апреля 2012

Так как Color является структурой, он имеет много свойств, отличных от значений 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);
2 голосов
/ 03 апреля 2012

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

Color.Red.ToString()           : "Color [Red]"
Color.FromArgb(...).ToString() : "Color [A=255, R=255, G=0, B=0]"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...