Вопрос

Why does this evaluate to false?

Color.FromArgb(255, 255, 255, 255) == Color.White

Update It's by design.

Here's a copy from the decompiled Equals function in the Color structure:

public override bool Equals(object obj)
{
    //probably failure to convert from C++ source,
    //the following line should be invalid in C#, nevermind
    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;
}

My question is why on earth would MSFT have me comparing to white the ugly way?!?!?

static bool AreEqual(Color a, Color b)
{
  if (!a.Equals(b))
  {
    return
      a.A == b.A &&
      a.R == b.R &&
      a.G == b.G &&
      a.B == b.B;    
  }
  return true;
}

Also, another thing I don't get why the 1-arg overload of the FromArgb function in Color takes an int, it should be able to take a uint (0xffffffff)

Это было полезно?

Решение

This is just how colors in .NET work:

This structure only does comparisons with other Color structures. To compare colors based solely on their ARGB values, you should do the following:

if ( color1.ToArgb() == color2.ToArgb()) ...

This is because the .Equals and == operators determine equivalency using more than just the ARGB value of the colors. For example, Color.Black and Color.FromArgb(0,0,0) are not considered equal since Color.Black is a named color and Color.FromArgb(0,0,0) is not.

Edit: additional answers.

My question is why on earth would MSFT have me comparing to white the ugly way?!?!?

If you're comparing colors in such a way that you want to know whether they're exactly the same color down to the values of the ARGB components, then you should be comparing them in the "ugly" way. If you're comparing the colors in the same way that most .NET programmers use the Color structure, then you only want to know if some color is White or Red or Chartreuse, and the "pretty" way (using Equals and ==) is simple, easy to use, and very readable.

Also, the "ugly" way isn't the method you posted, it's this:

if (color1.ToArgb() == color2.ToArgb()) ...

which isn't really that ugly.

Also, another thing I don't get why the 1-arg constructor of Color takes an int, it should be able to take a uint (0xffffffff)

I would say it should not be able to take a uint, thanks to the inevitable confusion and color errors that would cause. It's easy to write a method to do this.

Другие советы

Color is a structure and it contains more than the four byte values. Try this:

Color.FromArgb(255, 255, 255, 255).ToArgb() == Color.White.ToArgb()

The Color.FromArgb(255, 255, 255, 255) is not a named color, so its Name property will be ffffff and for the named color, Color.White the Name will be White. SO your comparison will not work

You can either use

Color.FromArgb(255, 255, 255, 255).ToArgb() == Color.White.ToArgb()

or

(Color.FromArgb(255, 255, 255, 255).R == Color.White.R && Color.FromArgb(255, 255, 255, 255).G == Color.White.G && Color.FromArgb(255, 255, 255, 255).B == Color.White.B && Color.FromArgb(255, 255, 255, 255).A == Color.White.A)

If i have to use HTML color (which I prefer), i use this: TextBox1.BackColor = System.Drawing.ColorTranslator.FromHtml("#FFFFFF")

The name is different, see these results in the Immediate window:

?Color.FromArgb(255, 255, 255, 255)
"{Name=ffffffff, ARGB=(255, 255, 255, 255)}"
    A: 255
    B: 255
    G: 255
    IsEmpty: false
    IsKnownColor: false
    IsNamedColor: false
    IsSystemColor: false
    Name: "ffffffff"
    R: 255

?Color.White
"{Name=White, ARGB=(255, 255, 255, 255)}"
    A: 255
    B: 255
    G: 255
    IsEmpty: false
    IsKnownColor: true
    IsNamedColor: true
    IsSystemColor: false
    Name: "White"
    R: 255

I just spent 30 minutes researching this cause you got me all curious about it too, but when i got back, looks like others posted exactly what i found. You're comparing two different things. You have to put them on the same level so you can then compare them, be it using one of the system.drawing properties or one of the other posters suggestions.

public static class ExtendsUInt32
    {
        /// <summary>
        /// Converts a System.UInt32 to a System.Drawing.Color.
        /// Ex: var orangyColor = (0xFFDDAA22).ToColor(); //some kind of orange
        /// <remarks>
        /// Easier than writing var orangyColor = Color.FromArgb(unchecked((int)0xFFDDAA22))),
        /// or var orangyColor = Color.FromArgb(255,230,200,50);
        /// </remarks>
        /// </summary>
        /// <param name="color">A uint containing bytes A,R,G,B in high-to-low order (whatever this stores as on your platform's endianness).</param>
        /// <returns>A freshly picked System.Drawing.Color.</returns>
        public static Color ToColor(this UInt32 color)
        {
            var bytes = BitConverter.GetBytes(color);
            if (BitConverter.IsLittleEndian) { bytes = bytes.Reverse().ToArray(); }
            return Color.FromArgb(bytes[0],bytes[1],bytes[2],bytes[3]);
        }
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top