C# метод перегрузки - PullRequest
0 голосов
/ 07 января 2020

Недавно я начал свои шаги с C #, и я читал о перегрузке метода. У меня есть следующий код в качестве расширения метода в классе, который я назвал 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;
            }
        }
}

Этот метод позволяет мне получить все элементы управления в указанном c элементе управления. Удивительно! Я могу вызвать этот метод следующим образом:

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

и, как я и ожидал ... Я могу go через каждый из элементов управления в указанном c элементе управления. (В данном случае ... TabControl)

Мой вопрос такой: Как я могу сделать этот метод перегрузкой метода ?, чтобы я принял в качестве первого аргумента список из нескольких элементов управления и выполнить этот же метод для каждого из них и вернуть его как одну коллекцию, которая может повторяться

Пример: я хочу сделать что-то похожее на следующее:

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

Пожалуйста, я Буду признателен за любую помощь .. Большое спасибо заранее

РЕДАКТИРОВАТЬ 1:

В моем классе утилит я создал новый метод с тем же именем и классом выглядит так, но я не знаю, как написать логи c этого метода для выполнения ожидаемого действия ...

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

Ответы [ 3 ]

1 голос
/ 07 января 2020

Это может быть довольно просто, и вы можете использовать существующую логику c для удобства. Вы захотите объявить другой метод расширения, который принимает IEnumerable<Control> вместо простого элемента управления.

Затем вы получите элементы управления для каждого элемента управления в списке, что приведет к созданию списка списков. Затем вы хотите свести это в один список Control. Вы можете выполнить sh, что с помощью LINQ SelectMany.

должно работать следующее:

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

Наряду с исходным определением GetAllChildren, у вас теперь есть перегруженный метод. Один принимает один Control в качестве параметра, другой принимает IEnumerable<Control> в качестве параметра.

0 голосов
/ 07 января 2020

Хотя подпись вашего исходного метода

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

, подпись должна быть

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

Я составил пример с целыми числами:

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

Таким образом, у нас есть две перегрузки, которые оба возвращают один элемент за раз. Второй использует первый.

0 голосов
/ 07 января 2020
public static IEnumerable<Control> GetAllChildren(this IEnumerable<Control> parents)
{
    return parents.SelectMany(p => p.GetAllChildren());
}

Добавить другое расширение, которое принимает коллекцию элементов управления.

Вы можете повторно использовать существующий метод расширения для каждого элемента управления в списке и использовать LINQ SelectMany, чтобы объединить дочерние элементы в одну коллекцию. ,

...