为什么“as”关键字在()强制转换时不起作用

时间:2010-04-30 19:43:58

标签: c# asp.net

//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;

如果我调试'as'关键字语句,我永远不会得到空引用(对象总是正确分配)。但是()转换会创建异常,除非它具有if语句。

编辑:经过大约15次课程后,我得到了一个空。似乎需要更多的运行来找到null,而()转换会捕获异常的速度有多快。

OLD:当每次类运行时,在'as'语句中有一个调试断点命中 - 永远不会为空。

当if中的'()'语句中有调试时,每次断点击中强制转换时都能正常工作。 Werid

9 个答案:

答案 0 :(得分:14)

  

//始终有效,将有效对象返回到_page     _page = _httpContext.Handler as System.Web.UI.Page;

这在技术上没有用。如果您发现_page将是null。它只是没有抛出错误。

as运算符用于告诉应用程序“我希望你尝试转换它。它可能没有,我知道这一点,所以不要抛出异常。我会相应地处理它。“

()转换用于告诉应用程序,“此对象将转换为此类型。如果没有错误,我需要了解它。”

两个演员表之间的差异(以及何时应该使用它们)是当你“认为”某些东西可以转换成另一种类型时,当你“知道”某些东西可以转换成另一种类型时。

这是Eric Lippert关于这个主题的一篇文章(改为他的博客没有被重新加入): http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

答案 1 :(得分:7)

From here:

  

使用as运算符与a不同   C#以三种重要方式进行投射:

     

当你变量时它返回null   试图转换不是   请求类型或继承   链,而不是扔一个   例外。它只能应用于   转换为的引用类型变量   参考类型。使用as   执行用户定义的转换,例如   作为隐式或显式转换   运算符,其中包含语法   做。实际上有两个完全   IL中定义的不同操作   处理这两个关键字(   castclass和isinst指令) -   它不仅仅是“语法糖”   由C#编写以使其与众不同   行为。 as运算符似乎   在v1.0和v1.1中略快一些   微软的CLR与投射相比   (即使在没有的情况下也是如此   无效的演员阵容会严重   降低铸件的性能   例外)。

答案 2 :(得分:4)

as cast和前缀强制转换之间的一个主要区别是,前缀强制转换会抛出异常,而as cast只会返回null。

答案 3 :(得分:0)

如果使用'as'运算符,如果转换失败,则只返回null。如果进行显式强制转换,则在转换失败时会抛出异常。在这种情况下,'as'向下倾斜到预期的正确类型。显式转换无法移动到所需类型。

作为一般规则,除非确实需要显式转换(例如当您需要转换为值类型时),否则应始终执行'as'。

答案 4 :(得分:0)

使用as TRIES将该对象强制转换为该特定类型,但在失败时返回null而不是抛出异常(而cast只是抛出异常)。您确定具有as子句的那个实际上是否返回了一个非空对象吗?

答案 5 :(得分:0)

@Tejs回答说的同样的事情。使用as的转换失败会产生null。

我会说与他不同,但作为一般规则,你应该总是使用一个明确的演员。我个人更倾向于在转换失败的情况下获得异常,而不是在另一个页面中获得(看似)无处的null引用异常。

as运算符的一个很好的用途是将数据转换出来并且不想检查System.DBNull

int someint = cmd.ExecuteScalar() as int? ?? 0;

答案 6 :(得分:0)

正如许多人指出的那样,as运算符在这种情况下返回null,避免了“问题”,但没有真正“正常”。

此网站很好地描述了使用as和投射之间的3个不同之处:

http://en.csharp-online.net/CSharp_FAQ:_What_is_the_difference_between_using_a_cast_and_the_as_operator

答案 7 :(得分:0)

实际上,这正是应该发生的事情。施法失败并抛出错误,因为施法无效。如果强制转换失败,as将默认为null。

答案 8 :(得分:0)

正如其他答案所指出的那样,归结为“as”将在无效演员阵容中返回null,而显式演员阵容将抛出异常

其他答案在是否倾向于其中一个方面存在争议。如果你打算使用“as”,你需要在某个时候处理它可能是null的事实。如果您打算使用显式转换,则必须处理可能的异常。根据用例,我倾向于一个或另一个。

我倾向于使用特定的强制转换,当我知道强制转换可以工作但编译器没有时,抛出异常就可以了(因为这是一个例外情况)。但是如果演员有合法的机会无效,我更喜欢使用“as”并测试null。这样可以避免捕获更加丑陋的异常并使调试更加困难。