Case 1
Assuming that the result of GetData() is of correct the correct type (ie something that is castable to the Hex struct the following will successfully compile and also work at runtime
struct Hex { ...}
...
Hex foo = (Hex)GetData();
because you can always write an explicit cast (ie you are telling the compiler you know what you are doing and it shouldn't care about possible incompatibilities)
Case 2
If the result of GetData() is something, that isn't castable to Hex
the same code
struct Hex { ...}
...
Hex foo = (Hex)GetData();
will still successfully compile (because you are overruling the compiler). But it will throw an InvalidCastException at runtime.
Case 3
Your second snippet won't even compile. Because the result of the as operator is nullable (ie as returns null if the typecheck fails) and you cannot assign null to a non-nullable struct.
struct Hex { ...}
...
Hex hex = actionData as Hex;
If you want to be able to compile this, you have to make the variable nullable like
Hex? hex = actionData as Hex?;
if (hex.HasValue) {
... //conversion succeeded
} else {
... //conversion failed and hex is null
}
or you make Hex a class instead of a struct. Because a class is a reference type which can also be null, but a struct is a value type which cannot be null.