2012-04-03 134 views
9

爲什麼這個斷言失敗?爲什麼這種顏色比較失敗?

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

執行此操作使用單一顏色如:Color.Red.ToArgb()==顏色。 FromArgb(255,0,0).ToArgb() – BlueVoodoo 2012-04-03 13:17:45

+0

請參閱http://stackoverflow.com/questions/7464994/how-to-compare-a-color-by-the-getpixel-method-and-a-color -pass-in-a-method-lik – nawfal 2013-07-25 14:10:36

回答

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

此外,'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); 
+0

不正確。如果Color b = Color.FromArgb(a.A,a.R,a.G,a.B);'name將爲null。 – 2012-04-03 13:50:09

+0

@lazyberezovsky你有沒有試過這個?我已經嘗試過,它的行爲如何在答案中說明。 – daryal 2012-04-03 13:58:25

+0

屬性'Name'只是在實際沒有的情況下生成字符串。我指出這一點,因爲比較中沒有使用屬性'Name'。只有實際的字段名稱被使用。 – 2012-04-03 14:01:27

2

這是System.Drawing.Color結構實施方式的結果。它有一個單獨的Name屬性,對於Color.Red爲「紅色」,但在您從Color.Red創建自己的Color時有所不同。 System.Windows.Media.Color(即WPF的Color實現)沒有表現出同樣的問題。