简体   繁体   中英

dynamic keyword or direct casting to type?

Let's say I have an object which type can assume various types at runtime. I just migrated some older .Net 3.5 code to 4.5 and have several occurrences of something like this:

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!");
    }
}

Are there any downsides on converting this method to use a dynamic type, besides the lack of syntax completion?

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!");
    }
}

There's two downsides:

  • Performance: accessing a property by using dynamic is much slower than a "normal" access
  • Static type checking: if you try to put, for instance, an int into your Text property, it'll blow up at runtime (whereas, without dynamic, the error would be detected during compilation).

To be honest, performance probably isn't an issue for most applications. That said, you can compromise by using dynamic only for dynamic dispatching:

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
}

This way you get static type checking and much cleaner code, without having to refactor the whole thing into real polymorphism (which is the preferred way, but you may not want to do if it's legacy code).

There's little value in using dynamic in your case if you're still doing the type check, in fact it would be less performant. I make use of dynamic if I can do something like:

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

I would write your code like:

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

I will get into detail in a generic way.

The downside of choosing the second dynamic way is that if you have custom types as branch in the if -Statement then if you refactor the name of a property of one custom type then you will get an exception at runtime. There is no compile time check. This is reason enough, for me, not to choose, in that case, this way.

In the other case if you have a direct -cast like in the first sample you avoid that problem because if you refactor a property then this is reflected through the all the Projects.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM