Overview
I was recently asked why some expressions didn't seem to be doing what the developer intended. Typically, this was due to the use of the short or byte data types. This post is a brief discussion on the related parts of the C# Language Specification (version 3.0).
Reference
You can find the C# Language Specification here:
Note that page references in this post may vary slightly from your view of the document due to printable page size differences on your computer.
Introducing literals
(pages 40-45 of the specification for those interested)
When you write a constant string or number in a C# program, you are defining a “literal”. The value of the expression is “literally equivalent” to the code. Here are some literals:
|
|
textual string |
|
|
integer number |
|
|
real number |
|
|
boolean value |
|
|
character literal |
I’ve been careful to avoid using the C# types for this, because there is a bit more to know in the numeric cases.
Firstly, you can only define the following numeric literal values directly:
- int
- uint
- long
- ulong
- float
- double (default for real numbers)
- decimal
Further, the type of literal can be specified with suffixes (case-insensitive) as follows:
|
|
unsigned (cannot be negative — only for integer literals) |
|
|
long (as opposed to int type — only for integer literals) |
|
|
double (double type — for real literals) |
|
|
float (float type — for real literals) |
|
|
decimal (or money type — for real literals) |
If the number does not include an exponent or a decimal point (with following digits) then the suffix is required to indicate a real number.
For an integer literal without a suffix, the type of the constant is the first integer type that can correctly represent the literal from the above list.
Note there are some exceptions to these rules that won’t generally affect you. Read the documentation if you want to find out more.
Secondly, some types cannot be directly defined as literal values:
Literal assignments to these types work only when the compiler can deduce that the result is acceptable, otherwise normal implicit conversion rules apply.
Understanding assignments
(pages 218ff.)
The next part of our problem is the assignment operator. In its simplest form, the assignment operator looks as follows:
X = Y
The compiler first determines the variable represented by the expression X. Then it works out the value of Y. Finally it attempts to store the value of Y in X, performing any needed implicit conversions.
Why is this important? The expression Y may not have the same type as X. In particular, there may not be an implicit narrowing conversion to X.
Here’s an example:
short x = 5;
short y = x + 5;
This will not compile. Why? Because the 5 has forced a widening conversion on “x” resulting in an “int” type expression. This can’t be converted to a “short” implicitly.
However, the compiler does perform constant coalescing. This means that a constant expression can be combined into a single constant. Additional rules are also applied to allow narrowing assignments that do not result in a loss of data. For example,
short y = 5 + 5;
This statement does compile and executes correctly. The following statement does not:
short y = 1000 * 1000;
The compile error given is: Error Constant value '1000000' cannot be converted to a 'short'.
Understanding expressions
(pages 129ff.)
Expressions are (mostly) evaluated from left to right. Different operators have different precedences too, so a multiplication takes priority over an addition. Each sub expression is evaluated in turn until the entire expression has been computed. Notice that it will perform widening conversions as needed along the way which may give you unexpected behaviour.
To see an example of this working as you might expect, have a look here:
http://msdn.microsoft.com/en-us/library/3b1ff23f.aspx
Versions
- Microsoft .NET Framework 3.5
- Microsoft .NET Framework 2.0
- C# Language Specification 3.0
- C# Language Specification 2.0
- Visual Studio 2005/8
Metadata
- Categories: Software Development, .NET, C#
- Additional keywords: language intrinsics, expressions, assignments, conversions
- Technorati Tags: .NET, software development, CSharp, C#, expressions, assignments, compilation, conversion, data types, literals