为什么这种颜色比较失败?

时间:2012-04-03 13:13:15

标签: c# colors

为什么这个断言失败了?

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

5 个答案:

答案 0 :(得分: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值。
  5. 因此,如果要比较颜色值,则应使用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());
    

    但这没有任何意义,因为您可以在程序的每个位置使用单色实例:)

答案 1 :(得分:2)

Color.Red是一种命名颜色,而Color.FromArgb(...)则不是。Color.Red.ToString() : "Color [Red]" Color.FromArgb(...).ToString() : "Color [A=255, R=255, G=0, B=0]" 。因此,即使它们具有相同的ARGB值,它们也不被认为是平等的。请注意,字符串表示也不同:

{{1}}

答案 2 :(得分: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;
}

答案 3 :(得分:2)

由于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);

在结构中也覆盖'Equals',以便检查结构的等价性;

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

答案 4 :(得分:2)

这是System.Drawing.Color结构实现方式的结果。它有一个单独的Name属性,Color.Red为“红色”属性,但是当您从Color创建自己的Color.Red时,属性会有所不同。 System.Windows.Media.Color(即WPF的Color实施)没有出现同样的问题。