C# - 一个 Action<> 是否可以有多个方法签名?

发布于 2024-08-02 15:22:46 字数 557 浏览 1 评论 0 原文

在 C# 中,是否可以让一个对象对一个 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");
    }
}

答案似乎是否定的,那么实现这样的事情的正确方法是什么? (试图解决的实际问题已经以不同的方式解决了,这只是好奇心)

In C#, is it possible to have an object that has multiple method signatures for an Action<> or delegate? Like this:

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

The answer seems to be no, so what is the proper way to implement something like that? (The actual problem this was trying to solve has been solved a different way, this is just curiosity at this point)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

戒ㄋ 2024-08-09 15:22:46

委托单个方法的抽象(当然,具有相似签名的多个方法可以由单个委托表示,但从调用者的角度来看,它的行为就像一个单个方法,因此这里无关紧要。)单个方法具有多个签名是没有意义的。因此,委托实例具有特定的签名。重载决议对于代表来说没有任何意义。它不是您从中选择的方法组。您直接指向一个方法并说“调用它”。

这个问题有什么解决办法吗?

我不清楚真正的问题是什么。这可能就是您正在寻找的:

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

A delegate is an abstraction of a single method (of course, several methods with similar signatures can be represented by a single delegate but from the caller's perspective, it behaves just like a single method, so that's irrelevant here.) It doesn't make sense for a single method to have multiple signatures. Hence, a delegate instance has a specific signature. Overload resolution does not have any meaning for delegates. It's not a method group you're choosing from. You're directly pointing to a method and saying "call this."

What's the solution to this problem?

It's not clear to me what the actual problem is. This might be what you're looking for:

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");
    }
}
晨曦÷微暖 2024-08-09 15:22:46

Delegate 类型是抽象的,只能创建基于完全类型化签名的委托。因此,在不提供 Delegate 模板的情况下不可能只创建任何方法的委托,但仍然可以使用现有的委托类型进行分配,例如 Action 或 < code>Action

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

可以编译,但我还没有尝试过它用于任何有目的的目的。

The Delegate type is abstract and only delegates based on fully typed signatures can be created. Thus it is impossible to just create a delegate to any method without providing a Delegate template, but it is still possible to assign using an existing delegate type, such as Action or 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);
    }
}

This compiles, but I haven't tried it for any purposeful purpose.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文