//always works, returning a valid object into _page
_page = _httpContext.Handler as System.Web.UI.Page;
//Fails throwing the exception : Unable to cast object of type 'System.Web.DefaultHttpHandler' to type 'System.Web.UI.Page'
_page = (System.Web.UI.Page)_httpContext.Handler;
Я хотел бы знать, почему это происходит?
Править:
//Fixes the problem
if(_httpContext.Handler is System.Web.UI.Page)
_page = (System.Web.UI.Page)_httpContext.Handler;
Если я отлаживаю 'как' оператор ключевого слова, я никогда не получаю нулевую ссылку (объект, всегда присваиваемый правильно). Однако () бросок создает исключения, если он не имеет если statment.
Править: После того, как приблизительно 15 пробегают класс, я смог получить пустой указатель. Кажется, что потребовалось больше выполнений для нахождения пустого указателя по сравнению с тем, как быстро () состав исполнителей поймает исключение.
СТАРЫЙ: Когда существует отладка в 'как' оператор каждый раз, когда класс выполняет хиты точки останова - никогда пустой указатель.
Когда существует отладка в' ()' оператор в, если, каждый раз точка останова совершает нападки, бросок работает правильно. Werid
// всегда работает, возвращая правильный объект в _page _page = _httpContext.Handler as System.Web.UI.Page;
Технически это не работает. Если вы заметите, _page
будет null
. Это просто не привело к ошибке.
Оператор as
используется для того, чтобы сказать приложению: "Я хочу, чтобы ты попытался преобразовать это. Это может не получиться, и я это знаю, поэтому не выбрасывайте исключение. Я поступлю с ним соответствующим образом".
Преобразование ()
используется, чтобы сказать приложению: "Этот объект будет приведен к этому типу. Если это не так, что-то не так, и я должен знать об этом."
Разница между двумя приведениями (и когда их следует использовать) заключается в том, когда вы "думаете", что что-то можно привести к другому типу, и когда вы "знаете", что что-то можно привести к другому типу.
Вот статья Эрика Липперта на эту тему (изменена на его блог без повторной подачи): http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx
Использование оператора as отличается от преобразования в C # тремя важными способами:
Он возвращает значение null когда переменная, которую вы пытаетесь преобразовать, не относится к запрошенному типу или не входит в цепочку наследования , вместо того, чтобы генерировать исключение . Его можно применять только к переменным ссылочного типа, конвертируемым в ссылочные типы. Использование as не будет выполнять определенные пользователем преобразования, такие как в качестве операторов неявного или явного преобразования , которые синтаксис преобразования будет выполнять . На самом деле есть две совершенно разные операции, определенные в IL , которые обрабатывают эти два ключевых слова (инструкции castclass и isinst) - это не просто "синтаксический сахар" " написан на C #, чтобы добиться этого другого поведения . Оператор as работает немного быстрее в версиях 1.0 и 1.1 из Microsoft CLR по сравнению с преобразованием (даже в тех случаях, когда нет недопустимые преобразования, которые могут серьезно снизить производительность преобразования из-за исключений).
Использование as
ПОПЫТАЕТСЯ привести этот объект к определенному типу, но возвращает null
при неудаче вместо того, чтобы выбросить исключение (тогда как приведение просто выбрасывает исключение). Уверены ли вы, что тот, в котором есть предложение as
, действительно возвращает не null-объект?
Как отметили другие ответы, все сводится к тому, что "as" вернет null в случае некорректного приведения, тогда как явное приведение вызовет исключение.
В других ответах есть некоторые споры о том, стоит ли склоняться к тому или иному варианту. Если вы собираетесь использовать "as", то вам придется в какой-то момент столкнуться с тем, что это может быть null. Если вы собираетесь использовать явное приведение, вам придется иметь дело с возможным исключением. В зависимости от конкретного случая использования я склоняюсь к тому или иному варианту.
Я склоняюсь к использованию явного приведения, когда я знаю, что приведение будет работать, но компилятор не знает, и выброс исключения будет нормальным (потому что это исключительный случай). Но если есть обоснованный шанс, что приведение будет недействительным, я предпочитаю использовать "as" и проверять на null. Это позволяет избежать вылавливания исключения, что более уродливо и затрудняет отладку, IMO.
Собственно, именно это и должно было случиться. Приведение не удалось и бросило и ошибка, потому что приведение недействительно. as
незаметно по умолчанию принимает значение null, если приведение не выполняется.
Одно из основных различий между приведением as и префиксным приведением заключается в том, что префиксное приведение приведет к исключению, а приведение as просто вернет null.
Как отмечают многие, оператор as
в этом случае возвращает null
, избегая " проблема "но не совсем" работает ".
На этом сайте есть хорошее описание трех различий между использованием в качестве
и преобразованием:
То же самое, что и в ответе @Tejs. Неудачное преобразование с as
выдает null.
Однако я буду говорить не так, как он, и в качестве общего правила вы всегда должны использовать явное приведение. Лично я предпочел бы получить исключение прямо там, где преобразование не удалось, чем на другой странице получить (казалось бы) из ниоткуда исключение в виде нулевой ссылки.
Одно из хороших применений оператора as
- это преобразование данных из базы данных и нежелание проверять System.DBNull
int someint = cmd.ExecuteScalar() as int? ?? 0;
Если вы используете оператор «as», в случае сбоя преобразования он просто возвращает null. Если вы выполните явное приведение, оно вызовет исключение, если преобразование завершится неудачно. В этой ситуации "as" отклоняется к ожидаемому правильному типу. Явное преобразование не может перейти к желаемому типу.
Как правило, вы всегда должны использовать «как», если вам действительно не нужно явное приведение (например, когда вам нужно преобразовать в типы значений).