动态关键字或直接转换为?

时间:2016-05-23 06:37:48

标签: c# dynamic

假设我有一个对象,该类型可以在运行时采用各种类型。我刚刚将一些较旧的.Net 3.5代码迁移到4.5并且出现了类似的事情:

private void DoStuffCast(object obj)
{
    if (obj is Button)
    {
        ((Button) obj).Content = "Foo";
        Console.WriteLine("Button!");
    }    

    if (obj is TextBox)
    {
        ((TextBox)obj).Text = "Bar";
        Console.WriteLine("Textbox!");
    }
}

除了缺少语法完成之外,将此方法转换为使用动态类型是否有任何缺点?

private void DoStuffDynamic(dynamic obj)
{
    if (obj is Button)
    {
        obj.Content = "Foo";
        Console.WriteLine("Button!");
    }    

    if (obj is TextBox)
    {
        obj.Text = "Bar";
        Console.WriteLine("Textbox!");
    }
}

3 个答案:

答案 0 :(得分:4)

有两个缺点:

  • 效果:使用dynamic访问某个媒体资源的速度远远低于"正常情况"访问
  • 静态类型检查:如果你试图将一个int放入你的Text属性中,它会在运行时爆炸(而没有动态,在编译期间会检测到错误)。

老实说,对于大多数应用程序来说,性能可能不是问题。也就是说,您只能通过dynamic进行动态调度来妥协:

private void DoStuffDynamic(object obj)
{
    dynamic d = obj;
    DoStuff(d);
}

private void DoStuff(Button button)
{
    button.Content = "Foo";
    Console.WriteLine("Button!");
}

private void DoStuff(TextBox textBox)
{
    textBox.Text = "Bar";
    Console.WriteLine("Textbox!");
}

private void DoStuff(object obj)
{
    // obj is neither Button or Textbox
}

通过这种方式,您可以获得静态类型检查和更清晰的代码,而无需将整个事物重构为真正的多态(这是首选方式,但如果它是遗留代码,您可能不想这样做。)< / p>

答案 1 :(得分:2)

如果你仍然在进行类型检查,那么在你的情况下使用dynamic没什么价值,事实上它的性能会更差。如果我能做类似的话,我会使用dynamic

private void DoStuffCast(dynamic obj)
{
   obj.Content = "Foo"; // ie, generically handle it.
   Console.WriteLine(obj.GetType().Name + "!!");
}

我会写你的代码:

private void DoStuffCast(Control obj) // whatever the base type is
{
    var btn = obj as Button;
    if (btn != null)
    {
        btn.Content = "Foo";
        Console.WriteLine("Button!");
        return;
    }

    vat tb = obj as Textbox;
    if (tb != null)
    {
        tb.Text = "Bar";
        Console.WriteLine("Textbox!");
        return;
    }
}

答案 2 :(得分:0)

我将以通用的方式详细介绍。

选择第二种dynamic方式的缺点是,如果您在types - Statement中有自定义if作为分支,那么如果您重构一个自定义类型的属性的名称然后你会在运行时得到一个异常。没有compile time检查。对我来说,这是足够的理由,在这种情况下,不要选择这种方式。

在另一种情况下,如果您在第一个示例中有direct - cast,则可以避免该问题,因为如果您重构某个属性,那么这将通过所有项目反映出来。