【问题标题】:dynamic keyword or direct casting to type?动态关键字或直接转换为类型?
【发布时间】:2016-09-19 22:15:23
【问题描述】:

假设我有一个类型可以在运行时假定各种类型的对象。我刚刚将一些较旧的 .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!");
    }
}

【问题讨论】:

标签: c# dynamic


【解决方案1】:

有两个缺点:

  • 性能:使用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
}

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

【讨论】:

  • 您不需要将objd 分开:如果您定义private void DoStuffDynamic(dynamic d) => DoStuff(d);,那么从调用者的角度来看,它就像参数具有object 类型一样工作。
【解决方案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;
    }
}

【讨论】:

    【解决方案3】:

    我将以一般的方式详细介绍。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-30
      • 1970-01-01
      • 1970-01-01
      • 2022-08-18
      • 2013-02-26
      • 1970-01-01
      • 2011-06-09
      相关资源
      最近更新 更多