看看这段c#代码:

byte x = 1;
byte y = 2;
byte z = x + y; // ERROR: Cannot implicitly convert type 'int' to 'byte'

在字节(或短)类型上执行的任何数学运算的结果都隐式地转换回整数。解决方案是显式地将结果转换回一个字节:

byte z = (byte)(x + y); // this works

我想知道的是为什么?是建筑吗?哲学吗?

我们有:

Int + Int = Int 长+长=长 浮+浮=浮 Double + Double = Double

所以为什么不呢:

字节+字节=字节 空头+空头=空头?

一点背景知识:我正在对“小数字”(即< 8)执行一个长列表的计算,并将中间结果存储在一个大数组中。使用字节数组(而不是int数组)更快(因为缓存命中)。但是大量的字节强制转换散布在代码中,使得代码更加难以阅读。


当前回答

就“为什么会发生这种情况”而言,这是因为正如其他人所说的那样,c#中没有为byte、sbyte、short或ushort的算术定义任何操作符。这个答案是关于为什么没有定义这些操作符。

我相信这主要是为了性能。处理器具有本地操作,可以非常快速地处理32位的算术。可以自动地将结果转换回字节,但如果您不希望发生这种行为,则会导致性能损失。

我认为这在一个带注释的c#标准中提到过。看……

编辑:令人恼火的是,我现在已经查看了带注释的ECMA c# 2规范、带注释的MS c# 3规范和注释的CLI规范,但据我所知,它们都没有提到这一点。我相信我已经看到了上面给出的理由,但如果我知道在哪里,我就被吹了。对不起,参考粉丝们:(

其他回答

我认为这是一个关于哪种操作更常见的设计决策……如果byte+byte = byte,可能更多的人会被强制转换为int类型的结果所困扰。

代码片段的第三行:

byte z = x + y;

实际上意味着

byte z = (int) x + (int) y;

因此,对字节没有+操作,字节首先被转换为整数,两个整数相加的结果是一个(32位)整数。

这是我对这个话题的大部分回答,首先是针对这里的一个类似问题。

默认情况下,所有小于Int32的整数运算在计算前四舍五入到32位。结果为Int32的原因仅仅是让它在计算后保持原样。如果检查MSIL算术操作码,它们操作的唯一整型数字类型是Int32和Int64。这是“故意的”。

如果您希望结果以Int16格式返回,则在代码中执行强制转换或编译器(假设)在“底层”发出转换都无关紧要。

例如,要执行Int16算术:

short a = 2, b = 3;

short c = (short) (a + b);

这两个数字将扩展为32位,然后相加,然后截短为16位,这是MS所希望的。

使用短(或字节)的优势主要是在有大量数据(图形数据、流等)的情况下存储。

我怀疑c#实际上是在调用int上定义的运算符+(它返回一个int,除非你在一个检查块中),并隐式地将你的bytes/shorts都转换为int。这就是为什么行为看起来不一致。

我已经测试了字节和int之间的性能。 int值:

class Program
{
    private int a,b,c,d,e,f;

    public Program()
    {
        a = 1;
        b = 2;
        c = (a + b);
        d = (a - b);
        e = (b / a);
        f = (c * b);
    }

    static void Main(string[] args)
    {
        int max = 10000000;
        DateTime start = DateTime.Now;
        Program[] tab = new Program[max];

        for (int i = 0; i < max; i++)
        {
            tab[i] = new Program();
        }
        DateTime stop = DateTime.Now;

        Debug.WriteLine(stop.Subtract(start).TotalSeconds);
    }
}

使用字节值:

class Program
{
    private byte a,b,c,d,e,f;

    public Program()
    {
        a = 1;
        b = 2;
        c = (byte)(a + b);
        d = (byte)(a - b);
        e = (byte)(b / a);
        f = (byte)(c * b);
    }

    static void Main(string[] args)
    {
        int max = 10000000;
        DateTime start = DateTime.Now;
        Program[] tab = new Program[max];

        for (int i = 0; i < max; i++)
        {
            tab[i] = new Program();
        }
        DateTime stop = DateTime.Now;

        Debug.WriteLine(stop.Subtract(start).TotalSeconds);
    }
}

结果如下: 字节:3.57s 157mo, 3.71s 171mo, 3.74s 168mo, CPU ~= 30% int: 4.05s 298mo, 3.92s 278mo, 4.28 294mo with CPU ~= 27% 结论: 字节使用更多的CPU,但它消耗更少的内存,它更快(可能是因为有更少的字节分配)