The most efficient way to determine the type of control in C # / WPF

I have a function that takes a control as a parameter and depending on the type of control (for example: TextBox, ComboBox, RadioButton, etc.), it executes code like:

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 it.

I know some other ways to do the same (for example: searching for a control type using GetType() , including a string representation of this type), and the Microsoft code analysis tool tells me to use instead as' of 'is' like this ( because it is better in performance):

 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 quite verbose and not very practical to read. I would like to be able to directly include a control type, but I cannot do this without resorting to using a string representation (which I don't like at all), since the case switch statement cannot contain a variable.

So what really is the best way to get the job done? and what do you think is the best way to do it? (not necessarily in terms of performance, but, for example, with the ability to read code)

Edit: since a lot is happening on the topic β€œwhy I use one common function, and not many types-specific methods”, here is another information:

I get a control variable from another part of the application I'm working on (type = Control), and I do something with this variable, depending on its type.

so in principle I have a choice between two options: either I use one common function, or I check the type of control in the body of the function so that at some point I execute the correct part of the code (the parameters that I have chosen now, but this can change ), or I check the type of control before calling the type method.

in any case, I have to turn on the type of control at some point, and this is the question of my question (no matter what I do with it, so to speak).

+6
syntax c # types wpf
source share
5 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 advantage of this approach is to improve maintainability:
1. You will find out that you have not registered several handlers for the same type of parameter (the dictionary will throw an exception)
2. You will have all your handler registrars separately, which allows you to easily find out which method processes a particular type of parameter.
3. Since the entire logic of the location of the handler is not repeated at all, it is quite easy to modify it to handle inhereting types, for example (my code does not do this, except for your code)

+8
source share

Well, you do not need to insert the second, use else if .

Secondly, why do you put all this into one method? It would be better, since at the time you call this, you need to know what type of control it is calling this method, and from there just do DoSomething for that type of control, and not all this conditional check.

0
source share

I think you are using the "is" operator perfectly. This is more readable, and you really don't have a useful alternative way if the control is not the one you were looking for anyway. I do not believe that temporary differences will be critical in this case.

You can exchange "else if" for a series of simple "if" s, returning from each individual if block, but this is a personal choice of style.

0
source share

It would be better to reorganize the general (controlling agnostic) functionalities into a separate function and have functions specific to control in special control functions.

You can then call the generic function from a control-specific function.

0
source share

This is the solution I would choose:

 internal class MyClass { private const string ButtonTypeAsString = "Button"; private const string CheckBoxTypeAsString = "CheckBox"; private const string TextBoxTypeAsString = "TextBox"; private static string GetTypeAsString(Control control) { string result = String.empty; if (result.Length == 0 && (control as Button) != null) { result = MyClass.ButtonTypeAsString; } if (result.Length == 0 && (control as CheckBox) != null) { result = MyClass.CheckBoxTypeAsString; } if (result.Length == 0 && (control as TextBox) != null) { result = MyClass.TextBoxTypeAsString; } if (result.Length == 0) { throw new InvalidOperationException("Control type is not handled by this method."); } return result; } internal static void DoSomething(Control control) { string controlTypeAsString = MyClass.GetTypeAsString(control); switch (controlTypeAsString) { case MyClass.ButtonTypeAsString: // Button stuff break; case MyClass.CheckBoxTypeAsString: // Checkbox stuff break; case MyClass.TextBoxTypeAsString: // TextBox stuff break; default: throw new InvalidOperationException("Unexpected Control type"); } } } 

... but I'm sure someone will find this excess. Personally, I like the readability of the switch and try to use it whenever possible. Also avoid including Magic Strings. Use const strings if possible.

If you do not mind, I ask what exactly are you trying to do? There may be a better solution that does not imply a Control type.

0
source share

All Articles