如何使用Func<>作为参数

本文关键字:参数 何使用 Func | 更新日期: 2023-09-27 18:01:42

我想使用Func作为参数来委托参数,如下所示:

delegate IPic Creator( Node pnode );
int CalSize( Creator c );
Func<Node,Ipic> funcCreator = ... ;
//then I want to use calSize
calsize( funcCreator ); // error
calsize( funcCreator.invoke ); // error

错误信息如下:

参数类型'System.Func<…节点,…IPic>'不能赋值给参数类型'…Creator'.

如代码所示,我想使用Func作为参数。我该怎么办?

如何使用Func<>作为参数

有很多方法可以做到这一点。

  1. 你可以定义一个执行funcCreator的委托,并将其传递给一个函数:

    Creator cr = x => funcCreator(x); 
    CalSize(cr);
    

    相同
    CalSize(x => funcCreator(x));
    
  2. 从您的funcCreator创建一个委托:

    CalSize(new Creator(funcCreator));
    
  3. Pass .Invoke method:

    CalSize(funcCreator.Invoke);
    

对于我来说,我会考虑将方法定义更改为:

int CalSize(Func<Node, IPic> c);

使你的函数更容易使用。
我没有发现使用委托是有用的,并且现在根本没有使用它们。当然,这只是我的观点和经验。如果你的项目成功地使用了委托,那么你可以忽略这部分:)

对于性能测试,我修改了您的代码,使Creator接受双精度并返回双精度(因为我没有NodeIPic)。

我使用了以下代码:

private static double lastResult;
// lastResult is used so that calculation within methods is not optimized away
public static void CalSize(Creator c)
{
    lastResult = c(10.0); 
}
public static void CalSize2(Func<double, double> f)
{
    lastResult = f(10.0);
}
static void Main()
{
    Func<double, double> funcCreator = x => Math.Pow(x, 20);
    Stopwatch sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < 10000000; i++)
    {
        // measured code goes here
    }
    sw.Stop();
}

不同方法的结果如下:

1. CalSize(x => funcCreator(x)); -> 579 ms
2. CalSize(new Creator(funcCreator)); -> 625 ms
3. CalSize(funcCreator.Invoke); -> 568 ms
4. CalSize2(funcCreator); -> 467 ms
所以,性能最低的方法是new Creator,因为它需要一些时间来构造一个委托。第一种方法和第三种方法是一样的,因为它们实际上做同样的事情。性能最好的方法是Func函数参数之一,在我的回答的最后描述了大约20%的优势。

还要注意,要产生~100毫秒的差异需要10 000 000次操作。想象一下您将要执行多少这样的操作,并且,很可能,您会理解这种差异是绝对微不足道的。只要选择对你方便的方法,不用考虑性能。

你需要把你的Func<>包装成一个委托:

(Creator)(pnode => funcCreator(pnode))