This question is actually pretty complicated...
Normally, a cast just tells the runtime to change one type to another. These have to be types that are compatible. For example an int
can always be represented as a long
so it is OK to cast it to a long
. Some casts have side-effects. For example, a float
will drop its precision if it is cast to an int
. So (int)1.5f
will result in int value 1. Casts are usually the fastest way to change the type, because it is a single IL operator. For example, the code:
public void CastExample()
{
int i = 7;
long l = (long)i;
}
Performs the cast by running the IL code:
conv.i8 //convert to 8-byte integer (a.k.a. Int64, a.k.a. long).
A parse is some function that takes in once type and returns another. It is an actual code function, not just an IL operator. This usually takes longer to run, because it runs multiple lines of code.
For example, this code:
public void ParseExample()
{
string s = "7";
long l = long.Parse(s);
}
Runs the IL code:
call int64 [mscorlib]System.Int64::Parse(string)
In other words it calls an actual method. Internally, the Int64 type provides that method:
public static long Parse(String s) {
return Number.ParseInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
And Number.Parse:
[System.Security.SecuritySafeCritical] // auto-generated
internal unsafe static Int64 ParseInt64(String value, NumberStyles options, NumberFormatInfo numfmt) {
Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
NumberBuffer number = new NumberBuffer(numberBufferBytes);
Int64 i = 0;
StringToNumber(value, options, ref number, numfmt, false);
if ((options & NumberStyles.AllowHexSpecifier) != 0) {
if (!HexNumberToInt64(ref number, ref i)) {
throw new OverflowException(Environment.GetResourceString("Overflow_Int64"));
}
}
else {
if (!NumberToInt64(ref number, ref i)) {
throw new OverflowException(Environment.GetResourceString("Overflow_Int64"));
}
}
return i;
}
And so on... so you can see it is actually doing a lot of code.
Now where things get more complicated is that although a cast is usually the fastest, classes can override the implicit and explicit cast operators. For example, if I write the class:
public class CastableClass
{
public int IntValue { get; set; }
public static explicit operator int(CastableClass castable)
{
return castable.IntValue;
}
}
I have overridden the explicit cast operator for int
, so I can now do:
public void OverridedCastExample()
{
CastableClass cc = new CastableClass {IntValue = 7};
int i = (int)cc;
}
Which looks like a normal cast, but in actuality it calls my method that I defined on my class. The IL code is:
call int32 UnitTestProject1.CastableClass::op_Explicit(class UnitTestProject1.CastableClass)
So anyway, you typically want to cast whenever you can. Then parse if you can't.