【问题标题】:Why does Color use Int32 over Byte?为什么 Color 在 Byte 上使用 Int32?
【发布时间】:2016-05-29 07:47:52
【问题描述】:

使用这个例子:

Color.FromArgb(Int32, Int32, Int32)

从指定的 8 位颜色值(红色、 绿色和蓝色)。 alpha 值隐含为 255(完全不透明)。 虽然这种方法允许为每种颜色传递一个 32 位的值 组件,每个组件的值限制为8位。

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

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

【问题讨论】:

标签: c# .net types


【解决方案1】:

Color 结构本身对 R、G、B 和 A 组件使用 byte 类型。

我认为他们已经选择使用int 作为参数类型,即使byte 就足够了,因为在将颜色的 ARGB 表示转换为 @ 时,它可以避免用户转换回类型987654325@ 结构,顾名思义。可以这样做:

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

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

另外,当值大于 255 或小于 0 时,他们可以并且确实提出ArgumentException,以正确通知用户他们已输入错误的输入,而不是仅仅限制值。也许他们在使用更高精度的Color 表示后忘记了对组件进行归一化?

【讨论】:

  • argb & 0xff000000 转换为字节总是零,你错过了一个转变。执行此操作的“正确”方法是(byte)(argb >> 24)。包括转换为字节。
  • @usr 糟糕,我的错。编辑了我的答案。
【解决方案2】:

我认为没有充分的理由。首先,我认为深入研究代码会提供一些见解,但我能找到的只是检查以确保 alpharedgreenblue 的值在 [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));
    }
}

我猜它在早期就变成了这种情况(我们在这里谈论的是 .NET 1.0),然后它就卡住了。

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

【讨论】:

    【解决方案3】:

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

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

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

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


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

    因为有人建议这样可以避免向下转换:我不明白这一点。扩大整数转换是隐式的,没有有意义的性能成本(通常没有)。

    【讨论】:

    • FWIW 字节符合,sbyte 不符合。
    • @AlexK。好吧,也许Color 的作者不知道:)(开玩笑。)
    猜你喜欢
    • 2011-03-01
    • 2010-10-30
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 2018-06-08
    • 1970-01-01
    • 2016-02-25
    相关资源
    最近更新 更多