What is the difference between "as" and (typecast)

Hey guys,
I was wondering why I would get an error with the following code (specifically the last line):

string[] races = Enum.GetValues(typeof(Race)) as string[];
string randomRace = races[UnityEngine.Random.Range(0, races.Length)];
characterRace = (Race) Enum.Parse( typeof( Race ), randomRace );

but not get an error with this code:

string[] races = Enum.GetValues(typeof(Race)) as string[];
string randomRace = races[UnityEngine.Random.Range(0, races.Length)];
characterRace = Enum.Parse( typeof( Race ), randomRace ) as Race;

I thought they were both ways of typecasting / performing the same task, however, the first code produces an error saying “The ‘as’ operator cannot be used with a non-nullable value type `Character.Race’”

Did you switch your code around by mistake? The 2nd should give you that error, not the 1st. As tries to cast it. If it can’t, null is returned. If null isn’t a valid value for your storage type, you get that error. Null is not a valid value for an enum.

Like homer already said: The as-cast only works with reference types.

The fundamental difference is:

c-style typecast

  • Can cast any type, so no matter if it’s a reference type or a value type
  • If the given variable / value can’t be casted into the target type this cast will throw an InvalidCast exception and terminate your function unless you catch the exception with a try-catch block

as typecast

  • Can only be used on reference types, so it won’t work on structs, enums, ints, floats, …
  • If this cast fails it will not throw an exception but instead return null. Since null can only be assigned to reference or nullable types this cast does only work on reference types.

Note: The as cast can be handy when you have a variable and want to test it for a specific type. However after the cast you can’t determine if the cast failed or if the given value already was null.

Example:

    BoxCollider col = GetComponent(typeof(Collider)) as BoxCollider;

if col is null this gameobject either don’t have any collider or it has one, but it’s not a BoxCollider

This line:

    BoxCollider col = (BoxCollider)GetComponent(typeof(Collider));

will throw an exception if the collider is not a BoxCollider. If it is a BoxCollider it is casted correctly. If there is no Colider at all col will be null since GetComponent returned null.