【问题标题】:Should I use (ObjectType) or 'as ObjectType' when casting in c#? [duplicate]在 c# 中进行转换时应该使用 (ObjectType) 还是“as ObjectType”? [复制]
【发布时间】:2009-07-28 10:48:27
【问题描述】:

可能重复:
Casting: (NewType) vs. Object as NewType

例如,我有一个名为 MyObjectType 的类,我想将事件的 sender 参数转换为这种类型。我通常会这样做:

MyObjectType senderAsMyType = (MyObjectType) sender;

我最近意识到也可以这样做:

MyObjectType senderAsMyType = sender as MyObjectType;

哪种方式最有效?这样我就可以使我的代码保持一致并始终使用其中一种方式。还是他们都有优点和缺点?如果是这样,请有人告诉我他们。

再次感谢,

【问题讨论】:

  • 没有人提到的重要一点是强制转换和“as”不做同样的事情。例如,如果您有一个用户定义的从 Foo 到 Bar 的显式转换,那么“(Bar)foo”会调用转换方法,但“foo as Bar”不会。确保您选择的选项实际上可以满足您的需求。让它正确,然后明确,然后才考虑让它更快。

标签: c# casting


【解决方案1】:

如果你想避免任何InvalidCastExceptions 使用

MyObjectType senderAsMyType = sender as MyObjectType;

否则使用

MyObjectType senderAsMyType = (MyObjectType)sender;

如果InvalidCastException 代表您的应用程序中真正的异常情况。

至于性能,我认为你不会发现两种不同类型的演员表之间有明显的区别。我感兴趣,所以我使用了Jon Skeet's BenchmarkHelper 并取得了证实我怀疑的结果:

测试:

using System;
using BenchmarkHelper;

class Program
{
    static void Main()
    {
        Object input = "test";
        String output = "test";

        var results = TestSuite.Create("Casting", input, output)
            .Add(cast)
            .Add(asCast)
            .RunTests()
            .ScaleByBest(ScalingMode.VaryDuration);
        results.Display(ResultColumns.NameAndDuration | ResultColumns.Score,
                results.FindBest());
    }

    static String cast(Object o)
    {
        return (String)o;
    }

    static String asCast(Object o)
    {
        return o as String;
    }

}

输出:

============ Casting ============
cast   30.021 1.00
asCast 30.153 1.00

【讨论】:

    【解决方案2】:

    我认为这个答案会有所帮助...

    Casting: (NewType) vs. Object as NewType

    【讨论】:

    • 啊抱歉,我搜索时找不到答案。谢谢
    【解决方案3】:

    基本区别:如果sender 不是MyObjectType 或其子类之一的实例,则第一个示例(直接转换)抛出异常;第二个(作为运算符)返回 null。

    它们都没有明显的好坏之分;您应该根据当前面临的情况使用其中一种。如果sender 不是MyObjectType 你想做什么?可能,在这种情况下,因为它是一个事件处理程序,抛出异常是非常好的......

    【讨论】:

      【解决方案4】:

      您应该尽可能使用(MyObjectType),因为如果转换失败,您将立即获得异常。使用as,您以后可能会在任何地方遇到 NullRef 异常。
      仅当您随后处理失败的演员表时才使用as

      【讨论】:

        【解决方案5】:

        他们做的事情略有不同。这取决于你想要什么。

        // Will throw an exception if the cast cannot be made
        MyObjectType foo = (MyObjectType)bar; 
        

        // Will return null if the cast cannot be made
        MyObjectType foo = bar as MyObjectType;
        

        您使用哪个取决于您?如果您预计演员阵容可能会经常失败(并且您对此感到满意),请选择 as 并在之后测试 null,如果您希望它永远不会失败,请选择 (type)

        请记住,如果引用可以是 null 并且您也需要知道这一点,请在演员表之前测试 null

        【讨论】:

          【解决方案6】:
          MyObjectType senderAsMyType = (MyObjectType) sender;
          

          如果发件人无法转换为MyObjectType,这将引发InvalidCastException

          MyObjectType senderAsMyType = sender as MyObjectType;
          

          如果发件人无法转换为MyObject,则senderAsMyType 将是null。此方法不能与值类型一起使用。

          我相信后者稍微快一点,但差异几乎是微不足道的。

          【讨论】:

          • 我认为速度是非常主观的,会受到您预期的施法失败百分比的影响。
          【解决方案7】:

          这取决于您对对象的期望。如果对象应该属于该类型,并且您需要访问该对象的成员,请使用:

          MyObjectType senderAsMyType = (MyObjectType) sender;
          

          如前所述,如果它无效,则会为您抛出 InvalidCastException

          如果它可能是那种类型,并且你只想在它是这种类型的情况下采取行动,使用'as',并检查是否为空

          MyObjectType senderAsMyType = sender as MyObjectType;
          
          if(senderAsMyType != null)
          {
              senderAsMyType.MyMethod()
          }
          

          但是,如果您只检查类型,但不需要对象,请使用“is”运算符,因为这在资源方面是最便宜的

          if(sender is MyObjectType)
              //do something
          

          【讨论】:

            【解决方案8】:

            不要太在意效率,还是根据语义来做决定吧。一个是否比另一个更有效将在很大程度上取决于个人情况,以及您预计它会失败多少次。

            直接转换“(ObjectType)”可能会失败,并且会抛出 InvalidCastException。

            “as”不会因异常而失败,但如果强制转换不起作用,则会返回一个空对象。

            如果演员表肯定是有效的,那就做演员表。这样,如果出现问题,您将得到异常并希望能够解决问题。

            如果您不确定对象类型,使用“as”并检查是否为空会很有用

            【讨论】:

              【解决方案9】:

              从最佳实践的角度来看,如果您期望不同类型的对象并且您的代码可以处理它们,您应该使用 as 关键字,例如

              public void MyFunction(MyObject obj)
              {
                obj.DoSomething();
                SpecializedObject specialized = obj as SpecializedObject;
                if(specialized!=null)
                {
                  specialized.DoSthSpecial();
                }
              }
              

              当你确定类型是你期望的类型时,使用正常的转换,你只需要转换它,因为技术原因:

              XmlSerializer xmlSerializer = new XmlSerializer(typeof(MyObject));
              MyObject obj = (MyObject)xmlSerializer.Deserialize(xml);
              

              这样不仅速度更快,而且不会隐藏错误。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-03-07
                • 1970-01-01
                • 2018-06-24
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多