Рассмотрим следующий код:
void Handler(object o, EventArgs e)
{
// I swear o is a string
string s = (string)o; // 1
//-OR-
string s = o as string; // 2
// -OR-
string s = o.ToString(); // 3
}
В чем разница между тремя типами кастинга (ладно, третий не кастинг, но вы получаете намерение). Какой из них должен быть предпочтительным?
string s = Convert.ToString(o)
:; 5-е:string s = $"{o}"
(или, что эквивалентно,string.Format
форма для более раннего C #)Ответы:
Выдает InvalidCastException, если
o
не являетсяstring
. В противном случае, правопреемникиo
кs
, даже еслиo
естьnull
.Назначает
null
вs
случаеo
не являетсяstring
или , еслиo
естьnull
. По этой причине вы не можете использовать его с типами значений (в этом случае оператор никогда не сможет вернутьсяnull
). В противном случае, назначаетo
наs
.Вызывает исключение NullReferenceException, если
o
естьnull
. Назначает то, чтоo.ToString()
возвращаетсяs
, независимо от типаo
.Используйте 1 для большинства конверсий - это просто и понятно. Я почти никогда не использую 2, так как если что-то не подходит, я обычно ожидаю исключения. Я видел только необходимость в этом типе возврата-нулевого функционала с плохо спроектированными библиотеками, которые используют коды ошибок (например, возвращают null = error вместо использования исключений).
3 не является приведением и является просто вызовом метода. Используйте его, когда вам нужно строковое представление нестрокового объекта.
источник
string s = (string)o;
Используйте, когда что-то определенно должно быть другим.string s = o as string;
Используйте, когда что-то может быть другим.string s = o.ToString();
Используйте, когда вам все равно, что это такое, но вы просто хотите использовать доступное строковое представление.источник
Это действительно зависит от того, знаете ли вы
o
строку и что вы хотите с ней делать. Если ваш комментарий означает, что наo
самом деле это строка, я бы предпочел прямой(string)o
акт - вряд ли она потерпит неудачу.Самым большим преимуществом использования прямого приведения является то, что при сбое вы получаете InvalidCastException , который в значительной степени сообщает вам, что пошло не так.
С
as
оператором, еслиo
это не строка,s
устанавливается значениеnull
, что удобно, если вы не уверены и хотите проверитьs
:Однако, если вы не выполните этот тест, вы будете использовать его
s
позже и получите исключение NullReferenceException . Они, как правило, встречаются чаще, и их гораздо сложнее отследить, когда они происходят в дикой природе, поскольку почти каждая строка разыменовывает переменную и может ее выбросить. С другой стороны, если вы пытаетесь привести к типу значения (любому примитиву или структурам, таким как DateTime ), вы должны использовать прямое приведение -as
не сработает.В особом случае преобразования в строку каждый объект имеет
ToString
, поэтому ваш третий метод может быть в порядке, еслиo
он не равен нулю, и вы думаете, чтоToString
метод может делать то, что вы хотите.источник
as
с типами значений Nullable . IEo as DateTime
не будет работать, ноo as DateTime?
будет ...if (s is string)
вместо этого?is
как вы сделаете это, вам все равно придется снова разыграть, так что у вас есть выбор, а затем - жесткий. По какой-то причинеas
проверка « и ноль» показалась мне лучше.Если вы уже знаете, к какому типу он может быть приведен, используйте приведение в стиле C:
Обратите внимание, что только с приведением в стиле C вы можете выполнять явное приведение типов.
Если вы не знаете, является ли это желаемый тип, и вы собираетесь использовать его, если это так, используйте в качестве ключевого слова:
Обратите внимание, что as не будет вызывать операторы преобразования типов. Он будет ненулевым, если объект не является нулевым и изначально имеет указанный тип.
Используйте ToString (), чтобы получить удобочитаемое строковое представление любого объекта, даже если он не может быть приведен к строке.
источник
Ключевое слово as хорошо в asp.net, когда вы используете метод FindControl.
Это означает, что вы можете оперировать с типизированной переменной, вместо того, чтобы потом
object
приводить ее, как если бы вы использовали прямое приведение:Это не большая вещь, но она экономит строки кода и присваивания переменных, плюс это более читабельно
источник
'as' основан на 'is', который является ключевым словом, которое проверяет во время выполнения, является ли объект полиморфно-совместимым (в основном, если приведение может быть выполнено) и возвращает нуль, если проверка не удалась.
Эти два эквивалентны:
Используя «как»:
Использование 'is':
Напротив, приведение в стиле c выполняется также во время выполнения, но выдает исключение, если приведение не может быть выполнено.
Просто чтобы добавить важный факт:
Ключевое слово «as» работает только со ссылочными типами. Вы не можете сделать:
В этих случаях вы должны использовать кастинг.
источник
2 полезно для приведения к производному типу.
Пусть животное:
получит подается с минимальным слепков.
источник
Согласно экспериментам на этой странице: http://www.dotnetguru2.org/sebastienros/index.php/2006/02/24/cast_vs_as
(на этой странице иногда появляются ошибки "недопустимого реферера", поэтому просто обновите, если это так)
Вывод: оператор as обычно быстрее, чем приведение. Иногда во много раз быстрее, иногда чуть быстрее.
Мне по личному вопросу «как» тоже удобнее читать.
Так как он быстрее и «безопаснее» (не исключает исключения) и, возможно, легче читается, я рекомендую использовать «как» все время.
источник
«(string) o» приведет к исключению InvalidCastException, поскольку прямого преобразования нет.
«o as string» приведет к тому, что s будет пустой ссылкой, а не будет выброшено исключение.
«o.ToString ()» сам по себе не является приведением типа, это метод, который реализуется объектом и, таким образом, так или иначе, каждым классом в .net, который «что-то делает» с экземпляром класс, к которому он обращен и возвращает строку.
Не забывайте, что для преобразования в строку также существует Convert.ToString (someType instanceOfThatType), где someType является одним из набора типов, по сути базовых типов каркасов.
источник
Все приведенные ответы хороши, если бы я мог добавить что-то: чтобы напрямую использовать строковые методы и свойства (например, ToLower), вы не можете написать:
Вы можете только написать:
но вы могли бы написать вместо этого:
as
Вариант более читаемый (по крайней мере , на мой взгляд).источник
(o as string).ToLower()
вместо нескольких запутанных скобок.Является предпочтительным, поскольку позволяет избежать потери производительности при двойном литье.
источник
Кажется, что они оба концептуально различны.
Прямой Кастинг
Типы не должны быть строго связаны. Это входит во все типы ароматов.
Такое ощущение, что объект собирается быть преобразован во что-то еще.
AS оператор
Типы имеют прямое отношение. Как в:
Такое ощущение, что вы собираетесь обращаться с объектом по-другому.
Образцы и ИЛ
источник
Я хотел бы обратить внимание на следующие особенности оператора as :
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/as
источник
При попытке получить строковое представление чего-либо (любого типа), которое потенциально может быть нулевым, я предпочитаю приведенную ниже строку кода. Он компактен, вызывает ToString () и правильно обрабатывает нули. Если o равно null, s будет содержать String.Empty.
источник
Поскольку никто не упомянул об этом, наиболее близким к instanceOf для Java по ключевому слову является следующее:
источник
Используйте прямое приведение,
string s = (string) o;
если в логическом контексте вашего приложенияstring
единственный допустимый тип. При таком подходе вы получитеInvalidCastException
и внедрите принцип Fail-fast . Ваша логика будет защищена от дальнейшей передачи недопустимого типа или получения исключения NullReferenceException, если используетсяas
оператор.Если логика ожидает несколько различных типов приведения
string s = o as string;
и проверьте ееnull
или используйтеis
оператор.В C # 7.0 появилась новая интересная функция для упрощения приведения и проверки соответствия шаблону :
источник
Следующие две формы преобразования типов (приведение) поддерживаются в C #:
|
(Резюме
• Преобразовать статический тип v в c в данном выражении
• Возможно, только если динамический тип v равен c или подтип c
• Если нет, генерируется исключение InvalidCastException
|
V как C
• Не смертельный вариант (с) v
• Таким образом, преобразуйте статический тип v в c в данном выражении
• Возвращает ноль, если динамический тип v не c или подтип c
источник