Ответ 1
Я считаю, что это потому, что приведение в SomeClass
может означать любое количество вещей в зависимости от того, какие конверсии доступны, тогда как приведение к ISomeInterface
может быть только ссылкой или преобразованием бокса.
Параметры:
-
Перенесите объект первым:
SomeClass obj2 = (SomeClass) (object) t;
-
Вместо этого используйте
as
:SomeClass obj2 = t as SomeClass;
Очевидно, что во втором случае вам также потребуется выполнить проверку недействительности позже, если t
не является SomeClass
.
EDIT: аргументы в пользу этого приведены в разделе 6.2.7 спецификации С# 4:
Вышеупомянутые правила не позволяют прямое явное преобразование из параметра неограниченного типа в тип без интерфейса, что может быть неожиданным. Причина этого правила заключается в том, чтобы предотвратить путаницу и сделать семантику таких преобразований понятными. Например, рассмотрим следующее выражение:
class X<T> { public static long F(T t) { return (long)t; // Error } }
Если было разрешено прямое явное преобразование t в int, можно легко ожидать, что
X<int>.F(7)
вернет 7L. Однако это не так, потому что стандартные числовые преобразования учитываются только тогда, когда типы известны как числовые во время привязки. Чтобы сделать семантику понятной, вместо этого должен быть записан вышеприведенный пример:class X<T> { public static long F(T t) { return (long)(object)t; // Ok, but will only work when T is long } }
Теперь этот код будет компилироваться, но выполнение
X<int>.F(7)
затем генерирует исключение во время выполнения, так как вложенный индекс не может быть преобразован непосредственно в длинный.