【问题标题】:Casting: (NewType) vs. Object as NewType [duplicate]铸造:(NewType)与对象作为NewType [重复]
【发布时间】:2010-09-05 08:57:51
【问题描述】:

这两个演员表之间实际上有什么区别?

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

通常,它们不应该都是指定类型的显式强制转换吗?

【问题讨论】:

  • 另见stackoverflow.com/questions/496096/…。这个是第一个,但那个有一个很好的答案。
  • 您发布了第二个最旧的问题,该问题与另一个问题重复(第一个问题已锁定)!恭喜你,我猜?
  • 这很有趣,因为这个是 3 个月前发布的 :) 但另一个有更详细的答案。

标签: c# .net


【解决方案1】:

如果源类型不能转换为目标类型,前者会抛出异常。后者将导致 sc2 为空引用,但也不例外。

[编辑]

我最初的答案肯定是最明显的区别,但作为 Eric Lippert points out,它不是唯一的。其他差异包括:

  • 您不能使用“as”运算符转换为不接受“null”作为值的类型
  • 您不能使用“as”来转换事物,例如将数字转换为不同的表示形式(例如,将浮点数转换为整数)。

最后,使用 'as' 与 cast 操作符,你也是在说“我不确定这是否会成功”。

【讨论】:

    【解决方案2】:

    另请注意,您只能将 as 关键字与引用类型或可为空的类型一起使用

    即:

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

    不会编译

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

    将编译。

    【讨论】:

    • 因为铸件无法转换
    【解决方案3】:

    当转换失败时,使用“as”进行类型转换当然要快得多,因为它避免了抛出异常的代价。

    但施法成功时并没有更快。 http://www.codeproject.com/KB/cs/csharpcasts.aspx 处的图表具有误导性,因为它没有解释它所测量的内容。

    底线是:

    • 如果您希望转换成功(即失败是例外),请使用转换。

    • 如果不知道会不会成功,使用“as”操作符,测试结果是否为null。

    【讨论】:

      【解决方案4】:

      这两种方法的区别在于第一个 ((SomeClass)obj) 可能会导致调用 type converter

      【讨论】:

        【解决方案5】:

        'as' 运算符“帮助”您将问题埋得更低,因为当提供不兼容的实例时,它将返回 null,也许您会将其传递给将通过的方法它到另一个等等,最后你会得到一个 NullReferenceException 这将使你的调试更加困难。

        不要滥用它。在 99% 的情况下,直接转换运算符更好。

        【讨论】:

        • 这里的建议非常中肯。读者,请考虑这一点。
        【解决方案6】:

        这是记住每个人遵循的过程的好方法,我在尝试决定哪个更适合我的情况时使用它。

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

        接下来应该很容易猜到它做了什么

        DateTime i = value as DateTime;
        

        在第一种情况下,如果无法转换值,则在第二种情况下,如果无法转换值,则会引发异常,则将 i 设置为 null。

        因此,在第一种情况下,如果在第二次转换中失败,则会进行硬停止,然后会进行软停止,稍后您可能会遇到 NullReferenceException。

        【讨论】:

          【解决方案7】:

          要扩展Rytmis's comment,您不能对结构(值类型)使用 as 关键字,因为它们没有空值。

          【讨论】:

            【解决方案8】:

            所有这些都适用于引用类型,值类型不能使用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
            }
            

            但是,如果您绝对确定 someObjectSomeClass 的一个实例,请使用强制转换。

            在 .Net 2 或更高版本中,泛型意味着您很少需要引用类的无类型实例,因此后者不太常用。

            【讨论】:

              【解决方案9】:

              对于那些有 VB.NET 经验的人,(type) 与 DirectCast 相同,“as type”与 TryCast 相同。

              【讨论】:

                【解决方案10】:

                如果转换尝试失败,括号中的转换将引发异常。如果转换尝试失败,“as”转换返回 null。

                【讨论】:

                  【解决方案11】:

                  这就像 Parse 和 TryParse 之间的区别。当您预期它可能会失败时,您使用 TryParse,但当您有充分的保证它不会失败时,您使用 Parse。

                  【讨论】:

                    【解决方案12】:

                    它们会抛出不同的异常。

                    () : NullReferenceException
                    如:InvalidCastException

                    这有助于调试。

                    “as”关键字尝试转换对象,如果转换失败,则返回 null。如果转换失败, () 转换运算符将立即抛出异常。

                    仅在您希望强制转换在非异常情况下失败时使用 C#“as”关键字。如果您指望强制转换成功并且没有准备好接收任何可能失败的对象,则应使用 () 强制转换运算符,以便引发适当且有用的异常。

                    代码示例和进一步解释:http://blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html

                    【讨论】:

                    • (-1) 因为不会抛出 InvalidCastException。
                    猜你喜欢
                    • 2012-02-20
                    • 2023-04-05
                    • 1970-01-01
                    • 2011-04-04
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-05-12
                    • 2014-10-25
                    • 2022-11-16
                    相关资源
                    最近更新 更多