Ваше понимание верно. Для меня это звучит как попытка микрооптимизации. Если вы уверены в типе, вам следует использовать обычное приведение. Помимо создания более разумного исключения, он также быстро дает сбой. Если вы ошибаетесь в своем предположении о типе, ваша программа немедленно выйдет из строя, и вы сможете сразу увидеть причину сбоя, а не ждать NullReferenceException
, ArgumentNullException
или даже логической ошибки в будущем. В общем, выражение as
, за которым не следует null
проверка, является запахом кода.
С другой стороны, если вы не уверены в приведении и ожидаете, что оно завершится ошибкой, вам следует использовать as
вместо обычного приведения, заключенного в блок try-catch
. Более того, рекомендуется использовать as
вместо проверки типа с последующим приведением. Вместо:
if (x is SomeType)
((SomeType)x).SomeMethod();
который генерирует isinst
инструкцию для is
ключевое слово и castclass
инструкция для приведения (эффективное выполнение приведения дважды) вы должны использовать:
var v = x as SomeType;
if (v != null)
v.SomeMethod();
Это только генерирует isinst
инструкцию. Первый метод имеет потенциальный недостаток в многопоточных приложениях, поскольку состояние гонки может привести к тому, что переменная изменит свой тип после успешной is
проверки и завершится ошибкой на линии приведения. Последний метод не подвержен этой ошибке.
Следующее решение не рекомендуется для использования в производственном коде. Если вы действительно ненавидите такую фундаментальную конструкцию в C #, вы можете подумать о переходе на VB или другой язык.
Если кто-то отчаянно ненавидит синтаксис приведения, он / она может написать метод расширения, имитирующий приведение:
public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ...
return (T)o;
}
и используйте аккуратный [?] синтаксис:
obj.To<SomeType>().SomeMethod()
person
mmx
schedule
26.01.2010
((T)x).SomeMethod()
, не так ли? ;) (шучу, ты конечно прав!) - person Lucero   schedule 26.01.2010as
работает быстрее, чем прямое приведение, только если оно терпит неудачу, чего и следовало ожидать. И даже если бы он был быстрее, это все равно неправильно. - person P Daddy   schedule 26.01.2010(f as T).SomeMethod()
;) - person MSalters   schedule 26.01.2010((T)x).SomeMethod()
вызовет InvalidCastException, что более полезно, чем исключение NullReferenceException, вызванное(x as T).SomeMethod()
. Исключение NullReferenceException в последнем случае не вызваноas
, а вызвано (попыткой) вызова метода. - person Heinzi   schedule 26.01.2010T a = (T)x
= левый,(x as T).SomeMethod();
= правый. Я доволен этим, и код чище из-за слишком большого количества скобок. кстатиif (x is T) (x as T).SomeMethod();
общие строки в моем коде, так как я могу скопировать условие if (с помощью скобок), изменить i на a и использовать его для вызова метода. - person Bitterblue   schedule 21.03.2014(x as T).SomeMethod()
существует, если SomeMethod является методом расширения, который разумно работает с нулевым аргументом, и если существует другой метод расширения с сигнатуройSomeMethod(this U u)
, гдеU
тип переменнойx
. В этом случае автор кода мог намереваться использовать метод расширения, который обычно компилятор не выбирает. Конечно, подойдет и гипс. Но в этом особом случае я бы тоже смог использоватьas
. - person JBSnorro   schedule 22.03.2015(x as T).SomeMethod()
, чтобы избежать лишних скобок, и он просто сообщает, что я знаю, что x is T, как Эрик Липперт написал в этом посте - так почему это так неправильно? - person BornToCode   schedule 31.08.2016(x as T)?.SomeMethod();
- person Victor   schedule 19.08.2019