A variable-reference is an expression that is classified as a variable. A variable-reference denotes a storage location that can be accessed both to fetch the current value and to store a new value.
variable-reference:
expression
In C and C++, a variable-reference is known as an lvalue.
5.5Atomicity of variable references
Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types. In addition, reads and writes of enum types with an underlying type in the previous list are also atomic. Reads and writes of other types, including long, ulong, double, and decimal, as well as user-defined types, are not guaranteed to be atomic. Aside from the library functions designed for that purpose, there is no guarantee of atomic read-modify-write, such as in the case of increment or decrement.
6.Conversions
A conversion enables an expression to be treated as being of a particluar type. A conversion may cause an expression of a given type to be treated as having a different type, or it may cause an expression without a type to get a type. Conversions can be implicit or explicit, and this determines whether an explicit cast is required. For instance, the conversion from type int to type long is implicit, so expressions of type int can implicitly be treated as type long. The opposite conversion, from type long to type int, is explicit and so an explicit cast is required.
int a = 123;
long b = a; // implicit conversion from int to long
int c = (int) b; // explicit conversion from long to int
Some conversions are defined by the language. Programs may also define their own conversions (§6.4).
6.1Implicit conversions
The following conversions are classified as implicit conversions:
Implicit conversions can occur in a variety of situations, including function member invocations (§7.4.4), cast expressions (§7.6.6), and assignments (§7.16).
The pre-defined implicit conversions always succeed and never cause exceptions to be thrown. Properly designed user-defined implicit conversions should exhibit these characteristics as well.
6.1.1Identity conversion
An identity conversion converts from any type to the same type. This conversion exists only such that an entity that already has a required type can be said to be convertible to that type.
6.1.2Implicit numeric conversions
The implicit numeric conversions are:
From sbyte to short, int, long, float, double, or decimal.
From byte to short, ushort, int, uint, long, ulong, float, double, or decimal.
From short to int, long, float, double, or decimal.
From ushort to int, uint, long, ulong, float, double, or decimal.
From uint to long, ulong, float, double, or decimal.
From long to float, double, or decimal.
From ulong to float, double, or decimal.
From char to ushort, int, uint, long, ulong, float, double, or decimal.
From float to double.
Conversions from int, uint, long, or ulong to float and from long or ulong to double may cause a loss of precision, but will never cause a loss of magnitude. The other implicit numeric conversions never lose any information.
There are no implicit conversions to the char type, so values of the other integral types do not automatically convert to the char type.
6.1.3Implicit enumeration conversions
An implicit enumeration conversion permits the decimal-integer-literal 0 to be converted to any enum-type and to any nullable-typewhose underlying type is an enum-type. In the latter case the conversion is evaluated by converting to the underlying enum-type and wrapping the result (§4.1.10).
6.1.4Implicit nullable conversions
Predefined implicit conversions that operate on non-nullable value types can also be used with nullable forms of those types. For each of the predefined implicit identity and numeric conversions that convert from a non-nullable value type S to a non-nullable value type T, the following implicit nullable conversions exist:
An implicit conversion from S? to T?.
An implicit conversion from S to T?.
Evaluation of an implicit nullable conversion based on an underlying conversion from S to T proceeds as follows:
If the nullable conversion is from S? to T?:
If the source value is null (HasValue property is false), the result is the null value of type T?.
Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping (§4.1.10) from T to T?.
If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?.
6.1.5Null literal conversions
An implicit conversion exists from the null literal to any nullable type. This conversion produces the null value (§4.1.10) of the given nullable type.
6.1.6Implicit reference conversions
The implicit reference conversions are:
From any reference-type to object.
From any class-type S to any class-type T, provided S is derived from T.
From any class-type S to any interface-type T, provided S implements T.
From any interface-type S to any interface-type T, provided S is derived from T.
From an array-type S with an element type SE to an array-type T with an element type TE, provided all of the following are true:
S and T differ only in element type. In other words, S and T have the same number of dimensions.
Both SE and TE are reference-types.
An implicit reference conversion exists from SE to TE.
From any array-type to System.Array.
From a single-dimensional array type S[] to System.Collections.Generic.IList and its base interfaces, provided that there is an implicit identity or reference conversion from S to T.
From any delegate-type to System.Delegate.
From the null literal to any reference-type.
Implicit conversions involving type parameters that are known to be reference types. See §6.1.9 for more details on implicit conversions involving type parameters.
The implicit reference conversions are those conversions between reference-types that can be proven to always succeed, and therefore require no checks at run-time.
Reference conversions, implicit or explicit, never change the referential identity of the object being converted. In other words, while a reference conversion may change the type of the reference, it never changes the type or value of the object being referred to.
Unlike array types, constructed reference types do not exhibit “covariant” conversions. This means that a type List has no conversion (either implicit or explicit) to List even if B is derived from A. Likewise, no conversion exists from List to List
A boxing conversion exists from a nullable-type to a reference type, if and only if a boxing conversion exists from the underlying non-nullable-value-type to the reference type.
Boxing a value of a non-nullable-value-type consists of allocating an object instance and copying the value-type value into that instance. A struct can be boxed to the type System.ValueType, since that is a base class for all structs (§11.3.2).
Boxing a value of a nullable-type proceeds as follows:
If the source value is null (HasValue property is false), the result is a null reference of the target type.
Otherwise, the result is a reference to a boxed T produced by unwrapping and boxing the source value.
Boxing conversions are described further in §4.3.1.
6.1.8Implicit constant expression conversions
An implicit constant expression conversion permits the following conversions:
A constant-expression (§7.18) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant-expression is within the range of the destination type.
A constant-expression of type long can be converted to type ulong, provided the value of the constant-expression is not negative.
6.1.9Implicit conversions involving type parameters
The following implicit conversions exist for a given type parameter T:
From T to its effective base class C, from T to any base class of C, and from T to any interface implemented by C. At run-time, if T is a value type, the conversion is executed as a boxing conversion. Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
From T to an interface type I in T’s effective interface set and from T to any base interface of I. At run-time, if T is a value type, the conversion is executed as a boxing conversion. Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
From T to a type parameter U, provided T depends on U. At run-time, if T is a value type and U is a reference type, the conversion is executed as a boxing conversion. Otherwise, if both T and U are value types, then T and U are necessarily the same type and no conversion is performed. Otherwise, if T is a reference type, then U is necessarily also a reference type and the conversion is executed as an implicit reference conversion or identity conversion.
If T is known to be a reference type (§10.1.5), the conversions above are all classified as implicit reference conversions (§6.1.6). If T is not known to be a reference type, the conversions described in the first two bullets above are classified as boxing conversions (§6.1.7).
6.1.10User-defined implicit conversions
A user-defined implicit conversion consists of an optional standard implicit conversion, followed by execution of a user-defined implicit conversion operator, followed by another optional standard implicit conversion. The exact rules for evaluating user-defined implicit conversions are described in §6.4.4.
6.1.11Anonymous function conversions and method group conversions
Anonymous functions and method groups do not have types in and of themselves, but may be implicitly converted to delegate types or expression tree types. Anonymous function conversions are described in more detail in §6.5 and method group conversions in §6.6.