开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜