简体   繁体   中英

C# Method Overload

Recently I started my steps with C # and I have been reading about method overload. I have the following code as a method extension within a class that I named Utilities:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Classes
{
    public static class Utilities
    {
        public static IEnumerable<Control> GetAllChildren(this Control parent)
        {
            Stack<Control> stack = new Stack<Control>();

            stack.Push(parent);

            while (stack.Any())
            {
                var next = stack.Pop();

                foreach (Control child in next.Controls)
                {
                    stack.Push(child);
                }

                yield return next;
            }
        }
}

This method allows me to obtain all controls within a specific control. Amazing! I can make a call to this method as follows:

private void Button1_Click(object sender, EventArgs e)
{
 foreach (Control control in TabControl.SelectedTab.GetAllChildren())
 {
   MessageBox.Show(control.Name);
 }
}

and as I expected ... I can go through each of the controls within a specific control. (In this case ... TabControl)

My question is this: How can I make this method a method overload?, so that I accept as a first argument a List of several controls, and execute this same method on each of them and return it as a single collection that can iterate

Example: I want to do something similar to the following:

private void ButtonSave_Click(object sender, EventArgs e)
{
    List<Control> controls = new List<Control> {
        TabControl1,
        TabControl2
    };

    foreach (Control control in controls.GetAllChildren())
    {
        MessageBox.Show(control.Name);
    }
}

Please, I would appreciate any help .. Thank you very much in advance

EDIT 1:

In my Utilities Class I have created a new method with the same name and the class looks like this, but I don't know how to write the logic of that method to perform the action I expect ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BASCAL.Classes
{
    public static class Utilities
    {
        public static IEnumerable<Control> GetAllChildren(this Control parent)
        {
            Stack<Control> stack = new Stack<Control>();

            stack.Push(parent);

            while (stack.Any())
            {
                var next = stack.Pop();

                foreach (Control child in next.Controls)
                {
                    stack.Push(child);
                }

                yield return next;
            }
        }

        public static IEnumerable<Control> GetAllChildren(this List<Control> parents)
        {
            if (parents.Any())
            {
                // Logic goes here!
            }
        }
    }
}

This can be pretty straight forward, and you can reuse your existing logic for convenience. You'll want to declare another extension method that accepts an IEnumerable<Control> instead of just a control.

You'll then get the controls for each control in the list, which will result in a list of lists. You then want to flatten that into a single list of Control . You can accomplish that with LINQ's SelectMany .

The following should work:

public static IEnumerable<Control> GetAllChildren(this IEnumerable<Control> controls) => controls.SelectMany(GetAllChildren);

Alongside your original definition of GetAllChildren , you now have an overloaded method. One accepts a single Control as it's parameter, the other accepts an IEnumerable<Control> as it's parameter.

public static IEnumerable<Control> GetAllChildren(this IEnumerable<Control> parents)
{
    return parents.SelectMany(p => p.GetAllChildren());
}

Add another extension that accepts a collection of controls.

You can reuse the existing extension method for each control in the list, and use LINQ SelectMany to combine the children into a single collection.

While your original method's signature is

public static IEnumerable<Control> GetAllChildren(this Control parent)

the signature of should be

public static IEnumerable<Control> GetAllChildren(this IEnumerable<Control> parents)

I made up an example with integer nubmbers:

struct Foo
{
    public int[] parts;
}

void Main()
{
    Foo f1 = new Foo() { parts = new int[] {3, 6, 9}};
    Foo f2 = new Foo() { parts = new int[] {4, 40, 400, 4000}};
    Foo f3 = new Foo() { parts = new int[] {3, 33, 333}};
    var fooList = new List<Foo>() { f2, f3 };

    foreach (var element in tellFoo(f1))
        Console.WriteLine(element);

    foreach (var element in tellFoo(fooList))
        Console.WriteLine(element);
}

IEnumerable<int> tellFoo(Foo x)
{
    foreach (var element in x.parts)
        yield return element;
}

IEnumerable<int> tellFoo(IEnumerable<Foo> foos)
{
    foreach (var foo in foos)
        foreach (var element in tellFoo(foo))
            yield return element;
}

So we have two overloads that both return one element at a time. The second one uses the first.

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