Кастинг:(НовыйТип) против.Объект как NewType

StackOverflow https://stackoverflow.com/questions/2483

  •  08-06-2019
  •  | 
  •  

Вопрос

Возможный дубликат:
Приведение против использования ключевого слова as в CLR

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

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

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

Это было полезно?

Решение

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

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

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

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

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

Другие советы

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

то есть:

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

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

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

скомпилируем.

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

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

Суть в следующем:

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

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

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

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

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

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

DateTime i = value as DateTime;

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

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

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

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

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

Все это относится к ссылочным типам, типы значений не могут использовать 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 или выше дженерики означают, что вам очень редко понадобится нетипизированный экземпляр ссылочного класса, поэтому последний используется реже.

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

Они будут генерировать разные исключения.
() :NullReferenceException
как :ИнвалидКастИсключение
Что может помочь в отладке.

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

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

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

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

Для тех из вас, кто имеет опыт работы с VB.NET, (тип) — это то же самое, что DirectCast, а «как тип» — то же самое, что TryCast.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top