Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

most effective way to determine a control's type in C#/WPF

Tags:

syntax

c#

types

wpf

I have a function that takes a control as parameter, and depending on the control's type (e.g.: TextBox, ComboBox, RadioButton etc...), it executes type-specific code:

internal static void DoSomething(Control control)
{
    if (control is Button)
    {
        // code for button
    }

    else if (control is CheckBox)
    {
        // code for CheckBox
    }

    else if (control is TextBox)
    {
        // code for TextBox
    }

    // etc.....
}

I am wondering if this is the best way to do.

I know of some other ways to do the same thing (e.g.: looking for the control's type using GetType(), switching on the string representation of this type), and Microsoft's code analysis tool tells me to use 'as' instead of 'is' like this (because it is better performance-wise):

internal static void DoSomething(Control control)
{
    Button button = control as Button
    if (button != null)
    {
        // code for button
    }

    else
    {
        CheckBox checkBox = control as CheckBox;
        if (checkBox != null)
        {
            // code for CheckBox
        }

        else
        {
            TextBox textBox = control as TextBox;
            if (textBox != null)
            {
                // code for TextBox
            }

            // etc.....
        }
    }
}

but I find this last solution rather wordy and not very practical to read. I'd like to be able to switch on the control's type directly, but am unable do to so without resorting to use the string representation (which I don't like at all) as a switch's case statement cannot contain a variable.

So what really is the best way to do performance-wise? and what is, in you opinion, the best way to do? (not necessarily performance-wise, but "code-readability-wise" for instance)

Edit: as a lot is going on on the subject of "why do I use one common function and not many type-specific methods", here is some more info:

I get a control variable from an other part of the app I'm working on (type = Control) and I have do "do something" with this variable, depending on its type.

so basically, I have the choice between 2 options: either I use one common function and check the control's type in the function's body so that I execute the right portion of the code at some point (options I have chosen for now, but this could change), or I check for the control's type BEFORE calling a type-specific method.

either way, I have to switch on the control's type at some point, and THIS is the subject of my question (regardless of what I do with it, if I may say so).

like image 945
David Avatar asked Mar 14 '11 14:03

David


1 Answers

I would use Dictionary for it and (also separate methods for each handler):

private static readonly Dictionary<Type, Action<Control>> _handlers
           = new Dictionary<Type, Action<Control>>();


// Handle.. methods
private static void HandleButton(Button button) { ... }
private static void HandleListbox(Listbox listbox) { ... }

private static void RegisterHandler<T>(Action<T> handler)
      where T: Control
{
    _handlers.Add(typeof(T), o => handler((T)o));
}

// invoke this method in static constructor
private static void InitializeHandlers()
{
    RegisterHandler<Button>(HandleButton);
    RegisterHandler<Listbox>(HandleListbox);
}

// finally usage:
internal static void DoSomething(Control control)
{
    var handler = _handlers[control.GetType()];
    handler(control);
}

The benefit for this approach is some maintainability improvement:
1. You will know that you haven't registered several handlers for same parameter type (dictionary will throw an exception)
2. You will have all your handler registrations separately which will allow you easily finding out which method handles particular parameter type.
3. Since all handler locating logic is not repeated at all it is pretty easy to modify it in order to handle inhereting types for example (my code doesn't do this but your code did)

like image 82
Snowbear Avatar answered Sep 28 '22 01:09

Snowbear