Предположим, что у меня есть общий метод:
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'
}
штопать. Справедливости ради, однако, я не могу сказать, должно ли это быть законным С# или нет. Что ж, если я попытаюсь сделать это по-другому?
if (typeof(T) == typeof(Hashtable)) {
var h = x as Hashtable; // works (and no, h isn't null)
}
Это немного странно. Согласно MSDN, expression as Type
(кроме оценки выражения дважды) совпадает с expression is type ? (type)expression : (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'
}
Единственное задокументированное различие между литьем и as
, которое я вижу, это "оператор as
выполняет только преобразования ссылок и преобразования бокса". Может быть, мне нужно сказать, что я использую ссылочный тип?
T Foo(T x) where T : class {
var h = ((Hashtable)x); // CS0030: Cannot convert type 'T' to 'System.Collections.Hashtable'
return x;
}
Что происходит? Почему as
работает нормально, в то время как кастинг даже не компилируется? Должна ли работа с кастом или работать с as
или существует какая-то другая разница между литьем и as
, которая не находится в этих документах MSDN, которые я нашел?