Ways to cast objects to a generic type
In relation to Casting generic type "as T&quo开发者_如何学编程t; whilst enforcing the type of T
And with the following example
private static T deserialize<T>(string streng) where T : class
{
XmlSerializer ser = new XmlSerializer(typeof(T));
StringReader reader = new StringReader(streng);
return ser.Deserialize(reader) as T;
}
and
private static T deserialize<T>(string streng)
{
XmlSerializer ser = new XmlSerializer(typeof(T));
StringReader reader = new StringReader(streng);
return (T)ser.Deserialize(reader);
}
I'm used to doing the object as Type
casting, so I was a little confused when I found that I couldn't just do that with T
. Then I found the question above and in that a solution to the as T
compiler error.
But why is where T : class
necessary when using object as T
and not when using (T)object
?
What is the actual difference between the two ways of casting the object?
Because as
implies the cast could fail and return null. Without a : class
, T
could be int
etc - which can't be null
. With (T)obj
it will simply explode in a shower of sparks; no need to handle a null
.
As an aside (re struct
), note you can use as
if it is known you are casting to a Nullable<>
- for example:
static T? Cast<T>(object obj) where T : struct
{
return obj as T?;
}
Casting with "as" is specified to 1) perform the cast if it can, and 2) return null
if it can't. This is problematic with an unconstrained generic parameter (your second example), because T could possibly be a value type (like int
), variables of which cannot hold null
.
When your generic parameter is constrained to be a reference type (with the class
constraint), the compiler can reason about your type a little more and understand that null
will always be a valid value for type T. Therefore, the "as"-style cast can be safely used.
As far as operator as
returns null
in failure case, variable should be a class or nullable struct:
Meanwhile cast
requires nothing like that and you can cast struct on struct.
(T)obj
throws if obj
isn't convertible to T
. You should use (T)obj
if you're certain that the conversion will work.
And use as
to replace a test with is
followed by a cast. Of course T needs to be nullable(either a reference type or a Nullable<T>
) since as
returns null on failure. The typical pattern is:
T x=y as T;
if(x!=null)
DoSomething(x);
Another difference is that as
only works for a subset of conversions. Overloaded casts etc will be ignored.
精彩评论