为什么Color使用Int32 over Byte?

时间:2021-11-21 15:01:57

Using this example:

使用此示例:

Color.FromArgb(Int32, Int32, Int32)

Color.FromArgb(Int32,Int32,Int32)

Creates a Color structure from the specified 8-bit color values (red, green, and blue). The alpha value is implicitly 255 (fully opaque). Although this method allows a 32-bit value to be passed for each color component, the value of each component is limited to 8 bits.

根据指定的8位颜色值(红色,绿色和蓝色)创建颜色结构。 alpha值隐式为255(完全不透明)。尽管此方法允许为每个颜色分量传递32位值,但每个分量的值限制为8位。

If the value of each component is limited to 8 bits, then why didn't they use Byte instead of Int32?

如果每个组件的值限制为8位,那么为什么他们不使用Byte而不是Int32?

In broader scope, I find people using Int32 very commonly, even when Int16 or Byte would suffice. Is there any particular reason for using Int32 generally over Int16, Byte, etc?

在更广泛的范围内,我发现人们使用Int32非常普遍,即使Int16或Byte就足够了。通常在Int16,Byte等上使用Int32有什么特别的原因吗?

3 个解决方案

#1


5  

My guess is that byte is less well supported by some .NET languages. Maybe it's not CLS compliant, I don't remember. These days nobody cares about CLS compliance anymore but in the 1.0 days this was an important feature level. Also note that VB.NET does not support unsigned types well which is an example of different support for integers across .NET languages.

我的猜测是某些.NET语言不太支持byte。也许它不符合CLS,我不记得了。这些天不再关心CLS合规性,但在1.0天内,这是一个重要的功能级别。另请注意,VB.NET不支持无符号类型,这是跨.NET语言对整数的不同支持的示例。

Using int for the constructor is especially weird because the A, R, G, B properties are byte.

使用int作为构造函数特别奇怪,因为A,R,G,B属性是字节。

I consider this to be an API design error.

我认为这是一个API设计错误。

The Color struct is not particularly beautiful in general. It does not only have ARGB values but also a KnownColor and a name. Many concerns have been crammed into this struct. For fun, the Equals method has a bug: return name.Equals(name);. This is always true, of course. This struct looks hastily done. You can tell from the Equals method that the code author did not know that strings have an overloaded equality operator. The operator equals of Color is the same 15 lines just copied over. I guess the true answer for this question is: The intern did it!

Color结构通常不是特别漂亮。它不仅具有ARGB值,还具有KnownColor和名称。许多问题都被塞进了这个结构中。为了好玩,Equals方法有一个bug:return name.Equals(name);.当然,这总是如此。这个结构看起来很仓促。您可以从Equals方法告诉代码作者不知道字符串有重载的相等运算符。颜色的运算符等于刚刚复制的15行。我想这个问题的真正答案是:实习生做到了!


Generally, Int32 is preferred because most arithmetic operations widen to 32 bits and it's an efficient integer width for common hardware. The shorter integer types are for more special uses.

通常,Int32是首选,因为大多数算术运算扩展到32位,并且它是普通硬件的有效整数宽度。较短的整数类型用于更多特殊用途。

Since it was suggested that this saves downcasting: I do not understand that point. Widening integer conversions are implicit and have no meaningful performance cost (often none).

因为有人建议这可以节省预测:我不明白这一点。扩展整数转换是隐式的,没有有意义的性能成本(通常没有)。

#2


1  

I don't think there is a good reason. First, I thought that digging into the code would provide some insight, but all I can find is that there are checks to ensure that the values of alpha, red, green and blue are within the [0..255] range, throwing an exception if not. Internally, the MakeArgb method is then called, which does use byte:

我认为没有充分的理由。首先,我认为挖掘代码会提供一些见解,但我能找到的是有检查以确保alpha,red,green和blue的值在[0..255]范围内,抛出一个如果不是例外。在内部,然后调用MakeArgb方法,它使用byte:

/// <summary>
///     [...]
///     Although this method allows a 32-bit value
///     to be passed for each component, the value of each
///     component is limited to 8 bits.
/// </summary>
public static Color FromArgb(int alpha, int red, int green, int blue)
{
    Color.CheckByte(alpha, "alpha");
    Color.CheckByte(red, "red");
    Color.CheckByte(green, "green");
    Color.CheckByte(blue, "blue");
    return new Color(Color.MakeArgb((byte)alpha, (byte)red, (byte)green, (byte)blue), Color.StateARGBValueValid, null, (KnownColor)0);
}

private static long MakeArgb(byte alpha, byte red, byte green, byte blue)
{
    return (long)((ulong)((int)red << 16 | (int)green << 8 | (int)blue | (int)alpha << 24) & (ulong)-1);
}

private static void CheckByte(int value, string name)
{
    if (value < 0 || value > 255)
    {
        throw new ArgumentException(SR.GetString("InvalidEx2BoundArgument",
                                    name,
                                    value,
                                    0,
                                    255));
    }
}

I guess it just became that way in the early days (we're talking .NET 1.0 here) and then it just stuck.

我想它在早期就变成了这种方式(我们在这里谈论.NET 1.0)然后它就停止了。

Also, there is the FromArgb(int) overload, which lets you set all 32 bits with one 32 bit value. Strangely, this is an int and not a unsigned int.

此外,还有FromArgb(int)重载,它允许您使用一个32位值设置所有32位。奇怪的是,这是一个int而不是unsigned int。

#3


0  

The Color struct itself uses the byte type for the R, G, B and A components.

Color结构本身使用R,G,B和A组件的字节类型。

I think that they've chosen to use int as the parameter types even when byte would suffice because it'll save the user from casting back to a type when converting an ARGB representation of the color to the Color struct, as the name says. Which would be done as:

我认为他们已经选择使用int作为参数类型,即使字节就足够了,因为它将保存用户在将颜色的ARGB表示转换为Color结构时转换回类型,如名称所示。这可以做到:

int argb = 0xffff0000; // Red
Color red = Color.FromArgb((argb & 0xff000000) >> 24, (argb & 0x00ff0000) >> 16, (argb & 0x0000ff00) >> 8, argb & 0x000000ff);

Making the coder cast each character to a byte manually would lengthen that line by "(byte)()".Length * 4 = 32 characters.

让编码器手动将每个字符转换为一个字节会使该行延长“(byte)()”。长度* 4 = 32个字符。

Plus, they can and do raise an ArgumentException when the values are greater than 255 or less than 0 to properly inform the user that they've entered the wrong input, instead of just clamping the values. Maybe they forgot to normalize the components after using a higher-precision Color representation?

另外,当值大于255或小于0时​​,它们可以并且确实引发ArgumentException,以正确地通知用户他们输入了错误的输入,而不是仅仅钳位值。也许在使用更高精度的Color表示后,他们忘记了对组件进行标准化?

#1


5  

My guess is that byte is less well supported by some .NET languages. Maybe it's not CLS compliant, I don't remember. These days nobody cares about CLS compliance anymore but in the 1.0 days this was an important feature level. Also note that VB.NET does not support unsigned types well which is an example of different support for integers across .NET languages.

我的猜测是某些.NET语言不太支持byte。也许它不符合CLS,我不记得了。这些天不再关心CLS合规性,但在1.0天内,这是一个重要的功能级别。另请注意,VB.NET不支持无符号类型,这是跨.NET语言对整数的不同支持的示例。

Using int for the constructor is especially weird because the A, R, G, B properties are byte.

使用int作为构造函数特别奇怪,因为A,R,G,B属性是字节。

I consider this to be an API design error.

我认为这是一个API设计错误。

The Color struct is not particularly beautiful in general. It does not only have ARGB values but also a KnownColor and a name. Many concerns have been crammed into this struct. For fun, the Equals method has a bug: return name.Equals(name);. This is always true, of course. This struct looks hastily done. You can tell from the Equals method that the code author did not know that strings have an overloaded equality operator. The operator equals of Color is the same 15 lines just copied over. I guess the true answer for this question is: The intern did it!

Color结构通常不是特别漂亮。它不仅具有ARGB值,还具有KnownColor和名称。许多问题都被塞进了这个结构中。为了好玩,Equals方法有一个bug:return name.Equals(name);.当然,这总是如此。这个结构看起来很仓促。您可以从Equals方法告诉代码作者不知道字符串有重载的相等运算符。颜色的运算符等于刚刚复制的15行。我想这个问题的真正答案是:实习生做到了!


Generally, Int32 is preferred because most arithmetic operations widen to 32 bits and it's an efficient integer width for common hardware. The shorter integer types are for more special uses.

通常,Int32是首选,因为大多数算术运算扩展到32位,并且它是普通硬件的有效整数宽度。较短的整数类型用于更多特殊用途。

Since it was suggested that this saves downcasting: I do not understand that point. Widening integer conversions are implicit and have no meaningful performance cost (often none).

因为有人建议这可以节省预测:我不明白这一点。扩展整数转换是隐式的,没有有意义的性能成本(通常没有)。

#2


1  

I don't think there is a good reason. First, I thought that digging into the code would provide some insight, but all I can find is that there are checks to ensure that the values of alpha, red, green and blue are within the [0..255] range, throwing an exception if not. Internally, the MakeArgb method is then called, which does use byte:

我认为没有充分的理由。首先,我认为挖掘代码会提供一些见解,但我能找到的是有检查以确保alpha,red,green和blue的值在[0..255]范围内,抛出一个如果不是例外。在内部,然后调用MakeArgb方法,它使用byte:

/// <summary>
///     [...]
///     Although this method allows a 32-bit value
///     to be passed for each component, the value of each
///     component is limited to 8 bits.
/// </summary>
public static Color FromArgb(int alpha, int red, int green, int blue)
{
    Color.CheckByte(alpha, "alpha");
    Color.CheckByte(red, "red");
    Color.CheckByte(green, "green");
    Color.CheckByte(blue, "blue");
    return new Color(Color.MakeArgb((byte)alpha, (byte)red, (byte)green, (byte)blue), Color.StateARGBValueValid, null, (KnownColor)0);
}

private static long MakeArgb(byte alpha, byte red, byte green, byte blue)
{
    return (long)((ulong)((int)red << 16 | (int)green << 8 | (int)blue | (int)alpha << 24) & (ulong)-1);
}

private static void CheckByte(int value, string name)
{
    if (value < 0 || value > 255)
    {
        throw new ArgumentException(SR.GetString("InvalidEx2BoundArgument",
                                    name,
                                    value,
                                    0,
                                    255));
    }
}

I guess it just became that way in the early days (we're talking .NET 1.0 here) and then it just stuck.

我想它在早期就变成了这种方式(我们在这里谈论.NET 1.0)然后它就停止了。

Also, there is the FromArgb(int) overload, which lets you set all 32 bits with one 32 bit value. Strangely, this is an int and not a unsigned int.

此外,还有FromArgb(int)重载,它允许您使用一个32位值设置所有32位。奇怪的是,这是一个int而不是unsigned int。

#3


0  

The Color struct itself uses the byte type for the R, G, B and A components.

Color结构本身使用R,G,B和A组件的字节类型。

I think that they've chosen to use int as the parameter types even when byte would suffice because it'll save the user from casting back to a type when converting an ARGB representation of the color to the Color struct, as the name says. Which would be done as:

我认为他们已经选择使用int作为参数类型,即使字节就足够了,因为它将保存用户在将颜色的ARGB表示转换为Color结构时转换回类型,如名称所示。这可以做到:

int argb = 0xffff0000; // Red
Color red = Color.FromArgb((argb & 0xff000000) >> 24, (argb & 0x00ff0000) >> 16, (argb & 0x0000ff00) >> 8, argb & 0x000000ff);

Making the coder cast each character to a byte manually would lengthen that line by "(byte)()".Length * 4 = 32 characters.

让编码器手动将每个字符转换为一个字节会使该行延长“(byte)()”。长度* 4 = 32个字符。

Plus, they can and do raise an ArgumentException when the values are greater than 255 or less than 0 to properly inform the user that they've entered the wrong input, instead of just clamping the values. Maybe they forgot to normalize the components after using a higher-precision Color representation?

另外,当值大于255或小于0时​​,它们可以并且确实引发ArgumentException,以正确地通知用户他们输入了错误的输入,而不是仅仅钳位值。也许在使用更高精度的Color表示后,他们忘记了对组件进行标准化?