Кастинг:(НовыйТип) против.Объект как NewType
Вопрос
Возможный дубликат:
Приведение против использования ключевого слова 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.