Приведение: (NewType) vs. Object как NewType

В чем собственно разница между этими двумя слепками?

SomeClass sc = (SomeClass)SomeObject;
SomeClass sc2 = SomeObject as SomeClass;

Обычно, разве они оба не должны быть явным приведением к указанному типу?


.net c#
person Michael Stum    schedule 05.08.2008    source источник
comment
См. Также stackoverflow.com/questions/496096/. Этот был первым, но у него есть хороший ответ.   -  person Jay Bazuzi    schedule 31.03.2010
comment
Вы разместили второй самый старый вопрос, который является дубликатом другого (первый заблокирован)! Поздравляю, я думаю?   -  person gparyani    schedule 09.10.2013
comment
Что забавно, потому что этот был опубликован 3 месяца назад :) Но у другого есть более подробные ответы.   -  person Michael Stum    schedule 09.10.2013


Ответы (12)


Первый вызовет исключение, если исходный тип не может быть приведен к целевому типу. Последнее приведет к тому, что sc2 будет пустой ссылкой, но не будет исключением.

[Редактировать]

Мой первоначальный ответ, безусловно, является наиболее заметной разницей, но, как сказал Эрик Липперт указывает, что это не единственный вариант. Другие отличия включают:

  • Вы не можете использовать оператор as для приведения к типу, который не принимает значение null в качестве значения.
  • Вы не можете использовать 'as' для преобразования таких вещей, как числа, в другое представление (например, float в int).

И, наконец, используя «as» вместо оператора приведения, вы также говорите: «Я не уверен, что это удастся».

person Rytmis    schedule 05.08.2008

Также обратите внимание, что вы можете использовать ключевое слово as только со ссылочным типом или типом, допускающим значение NULL.

ie:

double d = 5.34;
int i = d as int;

не будет компилироваться

double d = 5.34;
int i = (int)d;

будет компилировать.

person denny    schedule 05.08.2008
comment
потому что кастинг не конвертирует - person CiNN; 25.10.2008

Приведение типов с использованием «as», конечно, намного быстрее, когда приведение не выполняется, так как это позволяет избежать затрат на создание исключения.

Но когда бросок успешен, это не быстрее. График на http://www.codeproject.com/KB/cs/csharpcasts.aspx вводит в заблуждение, потому что не объясняет, что он измеряет.

Итог:

  • Если вы ожидаете, что приведение будет успешным (т. Е. Отказ будет исключительным), используйте приведение.

  • Если вы не знаете, удастся ли это сделать, используйте оператор «as» и проверьте результат на нуль.

person Joe    schedule 16.09.2008

Разница между этими двумя подходами заключается в том, что первый объект ((SomeClass) obj) может вызвать вызываемый преобразователь типов.

person Cristian Libardo    schedule 07.11.2008

Вот хороший способ запомнить процесс, которому следует каждый из них, который я использую, пытаясь решить, что лучше для моих обстоятельств.

DateTime i = (DateTime)value;
// is like doing
DateTime i = value is DateTime ? value as DateTime : throw new Exception(...);

а следующий должен легко догадаться, что он делает

DateTime i = value as DateTime;

в первом случае, если значение не может быть приведено, возникает исключение, во втором случае, если значение не может быть приведено, i устанавливается в значение null.

Таким образом, в первом случае выполняется жесткая остановка, если приведение не удается во втором приведении, выполняется мягкая остановка, и в дальнейшем вы можете столкнуться с исключением NullReferenceException.

person Nick Berardi    schedule 05.08.2008

Что ж, оператор "as" "помогает" избавиться от проблемы на более низком уровне, потому что, когда ему предоставляется несовместимый экземпляр, он вернет значение null, возможно, вы передадите его методу, который передаст его другому и так далее, и, наконец, вы получите исключение NullReferenceException, которое затруднит отладку.

Не злоупотребляйте этим. Оператор прямого приведения лучше в 99% случаев.

person Andrei Rînea    schedule 28.10.2010
comment
Здесь очень дельный совет. Читатели, пожалуйста, примите это к сведению. - person mbadawi23; 02.09.2017

Чтобы развернуть комментарий Ритмиса, вы не можете использовать как ключевое слово для структур (типов значений), поскольку они не имеют нулевого значения.

person Omer van Kloeten    schedule 07.09.2008

Все это относится к ссылочным типам, типы значений не могут использовать ключевое слово as, поскольку они не могут быть нулевыми.

//if I know that SomeObject is an instance of SomeClass
SomeClass sc = (SomeClass) someObject;


//if SomeObject *might* be SomeClass
SomeClass sc2 = someObject as SomeClass;

Синтаксис приведения быстрее, но только в случае успеха он намного медленнее выходит из строя.

Лучше всего использовать as, если вы не знаете тип:

//we need to know what someObject is
SomeClass sc;
SomeOtherClass soc;

//use as to find the right type
if( ( sc = someObject as SomeClass ) != null ) 
{
    //do something with sc
}
else if ( ( soc = someObject as SomeOtherClass ) != null ) 
{
    //do something with soc
}

Однако, если вы абсолютно уверены, что someObject является экземпляром SomeClass, используйте приведение.

В .Net 2 или выше универсальные шаблоны означают, что вам очень редко нужно иметь нетипизированный экземпляр ссылочного класса, поэтому последний используется реже.

person Keith    schedule 18.09.2008

Приведение в скобках вызывает исключение, если попытка приведения не удалась. Приведение "as" возвращает null, если попытка приведения не удалась.

person Community    schedule 05.08.2008

Это похоже на разницу между Parse и TryParse. Вы используете TryParse, когда ожидаете, что он может потерпеть неудачу, но когда у вас есть надежная уверенность, что он не подведет, вы используете Parse.

person ICR    schedule 08.08.2008

Для тех из вас, у кого есть опыт работы с VB.NET, (тип) такой же, как DirectCast, а «as type» - это то же самое, что и TryCast.

person Adam Says - Reinstate Monica    schedule 16.09.2008

Они выбрасывают разные исключения.

(): NullReferenceException
как: InvalidCastException

Что может помочь при отладке.

Ключевое слово as пытается преобразовать объект, и если преобразование завершается неудачно, возвращается null. Оператор приведения () немедленно вызовет исключение в случае сбоя приведения.

Используйте ключевое слово C # as только в том случае, если вы ожидаете, что приведение не удастся в неисключительном случае. Если вы рассчитываете на успешное приведение типов и не готовы к получению какого-либо объекта, который выйдет из строя, вам следует использовать оператор приведения (), чтобы возникло соответствующее и полезное исключение.

Примеры кода и дополнительные пояснения: http://blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html

person Steve Willard    schedule 05.08.2008
comment
(-1), поскольку не будет генерировать исключение InvalidCastException. - person Keith; 18.09.2008