Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is there any way to make this code shorter? [duplicate]

Tags:

c#

//list the controls from the  main form
foreach (Control c in Controls)
{
    if (c is ComboBox)
    {
        ((ComboBox)c).SelectedIndex = -1;
    }
    else if (c is TextBox)
    {
        ((TextBox)c).Text = "";
    }
    else if (c is CheckBox)
    {
        ((CheckBox)c).Checked = false;
    }
    //etc. with FIFTY different types to check against
}
like image 861
fre3land Avatar asked Oct 30 '15 17:10

fre3land


People also ask

How do I refactor a repeated code?

If the duplicate code is inside a constructor, use Pull Up Constructor Body. If the duplicate code is similar but not completely identical, use Form Template Method. If two methods do the same thing but use different algorithms, select the best algorithm and apply Substitute Algorithm.

How do you avoid code duplication in C++?

The conventional approach to reduce this kind of code duplication is to move the common code to a member function, which can be called from all the constructors. Usually, that member function is called init.

Is it okay to duplicate code?

Duplication is bad, but… Good developers are precise and careful and understand the risks and pitfalls of duplication in a code base—see the DRY (don't repeat yourself) principle, from The Pragmatic Programmer: “The alternative is to have the same thing expressed in two or more places.


3 Answers

One way is to add three overloaded methods for specific types, cast to dynamic, and make calls like this:

foreach (dynamic c in Controls) {
    ClearOut(c);
}
...
private static void ClearOut(ComboBox c) {
    c.SelectedIndex = -1;
}
private static void ClearOut(TextBox t) {
    t.Text = string.Empty;
}
private static void ClearOut(CheckBox c) {
    c.Checked = false;
}

Since c is dynamic, C# would postpone binding of the ClearOut method to runtime, giving you a clean-looking code. The downside of this approach is that C# is unable to tell you at compile-time if one of the overloads is missing.

like image 68
Sergey Kalinichenko Avatar answered Sep 30 '22 04:09

Sergey Kalinichenko


Use this method to set the properties of your controls:

public void Set(object obj, string property, object value)
{
    //use reflection to get the PropertyInfo of the property you want to set
    //if the property is not found, GetProperty() returns null
    var propertyInfo = obj.GetType().GetProperty(property);
    //use the C# 6 ?. operator to only execute SetValue() if propertyInfo is not null
    propertyInfo?.SetValue(obj, value);
}

Call it like this:

foreach (Control c in Controls)
{
    Set(c, "SelectedIndex", -1);
    Set(c, "Text", "");
    Set(c, "Checked", false);
}
like image 43
Domysee Avatar answered Sep 30 '22 05:09

Domysee


You can create a lookup from each supported type to an action that clears controls of that type, you can then add handlers to that lookup for each supported type:

public class ControlClearer
{
    private static Dictionary<Type, Action<Control>> lookup = new Dictionary<Type, Action<Control>>();

    static ControlClearer()
    {
        AddMapping((TextBox control) => control.Text = "");
        AddMapping((ComboBox control) => control.SelectedIndex = -1);
        AddMapping((CheckBox control) => control.Checked = false);
    }

    private static void AddMapping<T>(Action<T> clearAction)
        where T : Control
    {
        lookup[typeof(T)] = control => clearAction((T)(object)control);
    }

    public static void Clear<T>(T control)
        where T : Control
    {
        //todo support case where T isn't in the dictionary
        lookup[typeof(T)](control);
    }

    public static void Clear(Control control)
    {
        //todo support case where the type isn't in the dictionary
        lookup[control.GetType()](control);
    }
}
like image 43
Servy Avatar answered Sep 30 '22 06:09

Servy