Почему кастинг дает CS0030, в то время как "как" работает?

Предположим, у меня есть общий метод:

T Foo(T x) {
    return x;
}

Пока что хорошо. Но я хочу сделать что-то особенное, если это Hashtable. (Я знаю, что это полностью придуманный пример. Foo() тоже не очень интересный метод. Подыграй.)

if (typeof(T) == typeof(Hashtable)) {
    var h = ((Hashtable)x);  // CS0030: Cannot convert type 'T' to 'System.Collections.Hashtable'
}

Черт. Честно говоря, на самом деле я не могу сказать, должен ли это быть легальный C# или нет. Ну, а что если я попробую сделать это по-другому?

if (typeof(T) == typeof(Hashtable)) {
    var h = x as Hashtable;  // works (and no, h isn't null)
}

Это немного странно. Согласно MSDN, выражение как Type является (за исключением оценки выражения дважды) тем же самым, что и выражение как Type ? (type)выражение : (type)null.

Что произойдет, если я попытаюсь использовать эквивалентное выражение из документации?

if (typeof(T) == typeof(Hashtable)) {
    var h = (x is Hashtable ? (Hashtable)x : (Hashtable)null);  // CS0030: Cannot convert type 'T' to 'System.Collections.Hashtable'
}

Единственное документированное различие между кастингом и как, которое я вижу, это "оператор как выполняет только приведение ссылки и приведение бокса". Может быть, мне стоит сказать, что я использую тип ссылки?

T Foo(T x) where T : class {
    var h = ((Hashtable)x);  // CS0030: Cannot convert type 'T' to 'System.Collections.Hashtable'
    return x;
}

Что происходит? Почему так как работает нормально, а кастинг даже не компилируется? Должно ли кастинг работать, или как не работает, или есть какая-то другая языковая разница между кастингом и как, которой нет в этих MSDN-документах, которые я нашел?

19
задан Ken 21 September 2011 в 18:01
поделиться