views:

140

answers:

4

Consider this static test class:

public static class Test
{
    public static ushort sum(ushort value1, ushort value2)
    {
        return value1 + value2
    }
}

This causes the following compile error, with value1 + value2 underlined in red:

Cannot implicitly convert type 'int' to 'ushort'. An explicit conversion exists (are you missing a cast)?

Why?

+6  A: 

Like C and C++ before it, integers are implicitly widened when used with many operators. In this case, the result of adding two ushort values together is int.

Update:

More information: http://msdn.microsoft.com/en-us/library/aa691330(v=VS.71).aspx

I believe this was originally added in C/C++ because int was a native integer type (and yes, operations were faster on ints than on shorts on 32-bit architectures). I'm unsure of the full rationale for C#.

It does make you think about overflow/truncation considerations when you cast. Accidental overflow is more likely with the smaller integer types.

Stephen Cleary
So it's done that way because it's always been done that way?
Robert Harvey
Because the conversions have to exist anyway, it is easier to convert to a single type and apply the operators than to implement the operators separately for every type on top of the conversions that already exist.
murgatroid99
That, and the machine implicitly does arithmetic as 'int'. Also, if there are a lot of implicit conversions, it becomes far more likely that the compiler will pick a conversion that you didn't really intend. (See PL/I, for example.)
Eric Brown
See updated answer. I believe Eric's comment about the virtual machine arithmetic is the most likely reason why this is still done today.
Stephen Cleary
@Robert: "Otherwise, both operands are converted to type `int`." That would apply to two `ushort` operands.
R. Bemrose
+4  A: 

ushort

The following assignment statement will produce a compilation error, because the arithmetic expression on the right-hand side of the assignment operator evaluates to int by default.

ushort z = x + y;   // Error: conversion from int to ushort

To fix this problem, use a cast:

ushort z = (ushort)(x + y);   // OK: explicit conversion
Yuriy Faktorovich
+2  A: 

The available addition operators in C# only contemplate int, uint, long and ulong data types so in that case you are implicitly casting two ushort instances to int, then performing the addition and then returning an int that cannot be implicitly cast to ushort.

From the C# 4.0 specification, section 7.8.4 Addition operator, you can check that only the the following integer addition operators are available:

int operator +(int x, int y);
uint operator +(uint x, uint y);
long operator +(long x, long y);
ulong operator +(ulong x, ulong y);

The same section also states:

The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

Which explains why that expression results in an int.

João Angelo
+1  A: 

It is because addition or subtraction of ushorts doesn't necessarily result in a ushort. For example, the result could be < 0, which is not a ushort. So you need to give the compiler the hint to not complain by type casting it. I believe this should work: return (ushort)(value1 + value2);

AlvinfromDiaspar