Предположим, у меня есть общий метод:
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-документах, которые я нашел?