Problem with UInt16 arithmetic

Roger Garrett 1 Reputation point
2021-02-01T21:33:26.527+00:00

I've got some incredibly simple code. Three UInt16 variables. I can do simple assignments but it won't let me do simple arithmetic.

Here's the code

        UInt16 A = 1; // This is OK
        UInt16 B = 2; // This is OK
        UInt16 C = A * B; // Does NOT like this.
        C = A * 2; // Does NOT like this.

It highlights the A * B and reports that the A * B part Cannot implicitly convert type "int" to "ushort". An explicit conversion exists. Are you missing a cast?
Likewise for the A * 2 part;

Why doesn't it accept that? What is it expecting me to change?

Developer technologies C#
0 comments No comments
{count} votes

4 answers

Sort by: Most helpful
  1. Timon Yang-MSFT 9,606 Reputation points
    2021-02-02T02:38:53.523+00:00

    Let me talk about the conclusion first, this is by design.

    The result of A*B is of type Int32, and it is illegal to assign it to UInt16.

    This is called Numeric Promotion and is a rule to prevent data loss. You can find many explanations about this on the Internet, such as:

    Arithmetic operators (C# reference)

    Explain integer comparison with promotion

    For example, if A=65534 and B=10, then their addition or multiplication is beyond the scope of UInt16.

    If you are sure that the result will not exceed the range, you can force the conversion.


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. WayneAKing 4,931 Reputation points
    2021-02-02T02:42:54.847+00:00

    Promotion to int occurs automatically for arithmetic calculations.
    So the result of your arithmetic operations is an int.
    Cast the expressions to a UInt16.

    UInt16 A = 1; // This is OK
    UInt16 B = 2; // This is OK
    //UInt16 C = A * B; // Does NOT like this.
    UInt16 C = (UInt16)(A * B); // likes this.
    //C = A * 2; // Does NOT like this.
    C = (UInt16)(A * 2); // likes this.
    
    • Wayne
    0 comments No comments

  3. WayneAKing 4,931 Reputation points
    2021-02-02T03:10:08.7+00:00

    In addition to the references provided by Timon, the following
    page will show the limits of the various types. Knowing the
    maximum capacity of an arithmetic type is crucial to predicting
    whether or not the calculations you perform may result in data
    loss, due for example to an overflow.

    Integral numeric types (C# reference)
    https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types

    • Wayne
    0 comments No comments

  4. cheong00 3,486 Reputation points Volunteer Moderator
    2021-02-02T03:24:59.817+00:00

    Humm... I think this is not the most appropriate answer because it does not explain why the compiler won't complain the following code snippet:

    UInt32 A = 1;
    UInt32 B = 2;
    UInt32 C = A * B;
    Console.WriteLine(C);
    

    IMO the real reason is that the MSIL only define arithmetic operators for 32-bit operands only, so the parameter and result of multiplication is Int32/UInt32 before return, and that won't fit in UInt16 therefore explicit conversion is required.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.