Возможно ли иметь несколько сигнатур методов для действия <>?

2

В С# возможно ли иметь объект, который имеет несколько сигнатур методов для Action < > или делегата? Вот так:

class Foo
{
    public Action<string> DoSomething;
    public Action<string, string> DoSomething;
}

class Bar
{
    public Bar()
    {
        Foo f1 = new Foo();
        f1.DoSomething = (s) => { Console.Write(s) };
        Foo f2 = new Foo();
        f2.DoSomething = (s1, s2) => { Console.Write(s1 + s2) };

        f1.DoSomething("Hi");
        f2.DoSomething("Hi","World");
    }
}

Ответ, похоже, не такой, так что это правильный способ реализовать что-то подобное? (Фактическая проблема, которую пыталась решить, была решена по-другому, это просто любопытство в этой точке)

Теги:
delegates
action

2 ответа

4
Лучший ответ

A delegate является абстракцией одного метода (конечно, несколько методов со сходными сигнатурами могут быть представлены одним делегатом, но с точки зрения вызывающего, он ведет себя как один метод, так что здесь не имеет значения). Для одного метода не имеет смысла иметь несколько подписей. Следовательно, экземпляр делегата имеет определенную подпись. Разрешение перегрузки не имеет значения для делегатов. Это не группа методов, которую вы выбираете. Вы прямо указываете на метод и говорите "назовите это".

Какое решение этой проблемы?

Мне непонятно, какова реальная проблема. Это может быть то, что вы ищете:

class Foo {
    public Action<string> DoSomethingDelegate1;
    public Action<string,string> DoSomethingDelegate2;
    public void DoSomething(string s) { DoSomethingDelegate1(s); }
    public void DoSomething(string s, string t) { DoSomethingDelegate2(s, t); }
}

class Bar
{
    public Bar()
    {
        Foo f1 = new Foo();
        f1.DoSomethingDelegate1 = (s) => { Console.Write(s) };
        Foo f2 = new Foo();
        f2.DoSomethingDelegate2 = (s1, s2) => { Console.Write(s1 + s2) };

        f1.DoSomething("Hi");
        f2.DoSomething("Hi","World");
    }
}
  • 0
    Это на самом деле довольно близко к тому, что я искал (и что я в итоге делал), мой вопрос был больше о том, как можно избежать объявления дополнительного набора функций («DoSomething»). Я не верил, что это было, но я хотел проверить это.
0

Тип Delegate является абстрактным, и могут быть созданы только делегаты, основанные на полностью типизированных подписях. Таким образом, невозможно просто создать делегат для любого метода без предоставления шаблона Delegate, но по-прежнему можно назначить с использованием существующего типа делегата, такого как Action или Action<T>:

class Foo
{
    public Delegate Target { get; set; }

    public void Fire()
    {
        if (Target != null)
        {
            var pinfos = Target.Method.GetParameters();
            object[] args = new object[pinfos.Length];
            for (int i = 0; i < pinfos.Length; i++)
            {
                // Attempt to create default instance of argument:
                args[i] = Activator.CreateInstance(pinfos[i].ParameterType);
            }
            Target.DynamicInvoke(args);
        }
    }
}

class Bar
{
    public void Huppalupp()
    {
        Foo f = new Foo();
        f.Target = new Action(MethodThatTakesNothing);
        f.Fire();
        f.Target = new Action<string>(MethodThatTakesAString);
    }

    void MethodThatTakesNothing()
    {
        Console.WriteLine("Absolutely nothing.");
    }

    void MethodThatTakesAString(string s)
    {
        Console.WriteLine(s);
    }
}

Это компилируется, но я не пробовал его для целенаправленной цели.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню