双返回类型的多播委托,仅返回最后一个方法的结果,而不返回所有方法的结果

问题描述 投票:0回答:3

我是这个主题的新手,想知道是否有一种方法可以在使用多播委托的返回类型时获取所有方法的结果,而不仅仅是最后一个方法的结果?

这是我的代码:

class Program
    {
        public delegate double rectangleDelegate (double Width, double Heigth);
        class Rectangle
        {
            public double GetPerimeter(double Width, double Heigth)
            {
                return 2 * (Width + Heigth);
            }
            public double GetArea(double Width, double Heigth)
            {
                return Width * Heigth;
            }
        }
        static void Main(string[] args)
        {
            Rectangle rectangle = new Rectangle();

            rectangleDelegate obj = rectangle.GetArea;
            obj += rectangle.GetPerimeter;

            Console.WriteLine(obj(4, 2));

        }
    }

我尝试使用

void
作为我的方法和委托并打印结果。在这种情况下,我可以在控制台上看到两种方法的输出。但是当使用像
double
这样的返回类型时,我只能得到最后一个方法的输出。

我可以做一些事情来获取每个方法的返回并将其存储在变量或列表中吗? 或者期望多播代表做这样的事情是完全错误的方法吗?

c# delegates invoke multicastdelegate
3个回答
2
投票

你无法像这样获得所有的返回值。我知道的唯一方法是使用一点 hacky

GetInvocationList
:

rectangleDelegate obj = rectangle.GetArea;
obj += rectangle.GetPerimeter;

foreach(var del in obj.GetInvocationList())
{
    var result = (double)del.DynamicInvoke(4, 2);
    Console.WriteLine(result);
}

当然,这有点危险,因为它假设代表具有特定的格式。您可以将委托强制为您使用的类型,这意味着您不需要使用

DynamicInvoke
:

foreach(rectangleDelegate del in obj.GetInvocationList())
{
    var result = del(4, 2);
    Console.WriteLine(result);
}

或更安全的版本:

foreach(var del in obj.GetInvocationList().OfType<rectangleDelegate>())
{
    var result = del(4, 2);
    Console.WriteLine(result);
}

0
投票

我建议避免以这种方式使用多播委托。在事件之外使用多播委托是非常罕见的,我需要好好思考一下为什么有人会编写这样的代码。

如果您想调用多个委托并处理结果,我建议使用显式列表/数组:

var rectangleDelegateList = new rectangleDelegate[]{ 
    rectangle.GetArea, 
    rectangle.GetPerimeter
}
foreach(var method in rectangleDelegateList ){
    Console.WriteLine(method(4, 2));
}

这应该更容易阅读和理解。但是,我更喜欢这些方法分别返回

Area
Length
类型,因为这些应该被视为不同的东西。

如果确实有事件,通常会在事件参数对象中传递输入和输出:

public class MyEventArg{
    public double Width {get; init;}
    public double Height {get; init;}
    public double Result {get;set;}
}
public event EventHandler<MyEventArgs> myEvent;

private RaiseEvent(){
    var args = new MyEventArgs(){ Width = 4, Height = 2};
    myEvent?.Invoke(this, args);
    Console.WriteLine(args.Result);
}

但这也是我会小心的模式,因为您通常不期望来自任何事件处理程序的结果值。一种用例是关闭事件之类的情况,其中任何事件处理程序都可以取消关闭。


0
投票

另一种方法是更改委托并将结果添加到列表中:

public delegate void RectangleDelegate(double Width, double Height,
                                       List<double> results);

在不更改

Rectangle
类的情况下,我们得到:

var rectangle = new Rectangle();
var results = new List<double>();

RectangleDelegate rectDelegate = (w, h, r) => r.Add(rectangle.GetArea(w, h));
rectDelegate += (w, h, r) => r.Add(rectangle.GetPerimeter(w, h));

rectDelegate(4, 2, results);
foreach (double result in results) {
    Console.WriteLine(result);
}

请注意,我使用 lambda 表达式 将矩形方法的签名转换为委托所需的签名。

打印

8
12
© www.soinside.com 2019 - 2024. All rights reserved.