#1,048 – No Implicit Conversions between Signed vs. Unsigned

You can do an implicit numeric conversion when the conversion would not result in the loss of data.

You can never do an implicit conversion to convert between the signed vs. unsigned variants of a particular type, e.g. between short and ushort.

This makes sense, because the ranges of the signed vs. unsigned types overlap, but one is not inclusive of the other.  For example:

  • short :  -32,768 to 32,767
  • ushort :  0 to 65,535

You can’t do an implicit conversion between these types, in either direction.

You can, however, convert between these types using an explicit conversion (with a cast operator).  If the value to be converted is not representable in the target type, data will be lost but the assignment will succeed.  (How explicit casts fail).

            ushort myUnsignedShort = 40000;
            short myShort;

            // Compiles, but data is lost on
            // assignment
            myShort = (short)myUnsignedShort;

            // Now we'll get OverflowException
            myShort = checked((short)myUnsignedShort);

Here’s what the data looks like after the first assignment:

#1,047 – The Implicit Identity Conversion

One of the implicit conversions that exists in C# is the identity conversion, which states that an expression of a given type can be implicitly converted to that same type.

This sounds silly and unnecessary, but allows the compiler to know that assignments like the one below are allowed.

            int anInt = 12;

            // Identify conversion allows the
            // following assignment as an
            // implicit conversion
            int another = anInt;

#1,046 – Implicit vs. Explicit Conversions

conversion occurs in C# when you convert an expression of one type to a different type.  Often this occurs when you convert an instance of one type to an instance of another type.

Conversions can generally be broken down into two categories:

  • Implicit
    • Conversion can happen automatically
    • Guaranteed to succeed
    • No loss of data
  • Explicit
    • Requires a cast operator
    • Required when either chance of failure or when there will be data loss

Below are some examples of both numeric and reference conversions, implicit and explicit.

            int anInt = 12;

            // Implicit numeric conversion
            long aLong = anInt;

            // Explicit numeric conversion
            int newInt = (int)aLong;

            BorderCollie kirby = new BorderCollie("Kirby", 12);

            // Implicit reference conversion
            // - derived class to base class
            Dog d = kirby;

            // Explicit reference conversion
            // -  base class to derived class, may fail
            // (This example will throw an InvalidCastException
            //  because we're trying to convert a BorderCollie to a
            //  Terrier).
            Terrier t = (Terrier)d;

#1,011 – TryParse Indicates Whether a Parse Operation Will Succeed

You can use the Parse method to convert a string that represents a number to its equivalent numerical representation.

            string numberString = "108";
            int number = int.Parse(numberString);

If the string does not represent a value of the associated numeric type, or represents a numeric value that is outside the range of the type, a FormatException or OverflowException is generated.

            int n1 = int.Parse("3.4");    // FormatException

You can avoid the exception by using the TryParse method.  If the parse operation succeeds, the parsed value is stored in the output parameter and TryParse returns true.  If the parse operation does not succeed, the output parameter is not written to and TryParse returns false.  No exception is thrown.

            int n1;
            if (int.TryParse("3.4", out n1))
                Console.WriteLine("Parse worked--n1 contains number");
                Console.WriteLine("Can't parse");