C#:Func<>而不是方法?

发布于 2024-12-01 06:33:14 字数 464 浏览 3 评论 0 原文

对于所有了解这一点的人来说,这是一个好奇的问题:

使用 Func 而不是方法有什么坏处/缺点吗?简单的例子:

private static Func<int, int, DBContext, List<T>> Foo =
    (i1, i2, dbc) =>
        (i1 != 0) ? dbc.Bar(i2) : new List<T> { /*some default values ...*/ };

Vs

private static List<T> Foo(int i1, int i2, DBContext dbc)
{
    return i1 != 0 ? dbc.Bar(i2) : new List<T> { /*some default values ...*/ };
}

This is a curiosity questions for you all in the know:

Is there any harm/downside to using a Func instead of a method? Simple example:

private static Func<int, int, DBContext, List<T>> Foo =
    (i1, i2, dbc) =>
        (i1 != 0) ? dbc.Bar(i2) : new List<T> { /*some default values ...*/ };

Vs

private static List<T> Foo(int i1, int i2, DBContext dbc)
{
    return i1 != 0 ? dbc.Bar(i2) : new List<T> { /*some default values ...*/ };
}

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

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

发布评论

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

评论(6

别挽留 2024-12-08 06:33:15

我看到了几个缺点:

  • 性能影响(委托与方法) - 小,但没有
  • 参数名称(损害调用的可读性)
  • 定义本身可读性较差
  • 不可能重载(感谢 xanatos)

因为你什么也得不到 我只会在本地和小上下文,更喜欢静态方法

I see severale downsides:

  • performance impact (delegate vs method) - small but it's there
  • no parameternames (hurts readability on calls)
  • the definition itself is less readable
  • no overload possible (thanks to xanatos)

as you gain nothing I would only to so in a local and small context and prefer the static method

王权女流氓 2024-12-08 06:33:15

性能并不像最初看起来那么重要,调用委托和通过 v_table 分派的方法(虚拟实例方法)的成本是相当的。在这种情况下,对于静态方法,不使用委托可能会带来较小的性能提升。

您在这里发现的“技巧”是一种相当常见的技术,无需借助面向对象的编程技术(例如策略模式)即可实现功能分解。您可以将方法调用替换为对委托的调用。这个技巧的另一个好处是调用的语法是相同的。

然而,我会非常小心地应用这种技术。我通常使用它的目的是避免使用单一方法的接口,该方法不具有超过一两个参数(否则我会考虑使用参数对象或使用接口)。

C# 是一种多范式语言,每种范式都有其用途。函数范式(例如使用 Func 代替编译时已知方法)有其一席之地,面向对象范式也是如此。在您的情况下,使用 Func<> 没有任何好处,为了清楚起见,您应该使用传统方法。

Performance is not as much of an argument as it would seem originally, the cost of invoking a delegate and a method that is dispatched through the v_table (virtual instance methods) are comparable. In this case, for a static Method it is likely there is a small performance gain for not using the delegate.

The "trick" you discovered here is a fairly common technique to achieve functional decomposition without resorting to object-oriented programming techniques (e.g. the Strategy Pattern). You replace a method call with a call to a delegate. Another nice aspect of this trick is that the syntax for invocation is the same.

However, I would be extremely careful applying this technique. What I do usually use it for is to avoid Interfaces with a single method, that do not have more than one or two parameters (else I would consider using a Parameter Object or using an interface).

C# is a multi-paradigm language, and using each paradigm has its place. Functional paradigms (such as using Funcs instead of compile-time known methods) have their place, as do object oriented paradigms. In your case, there is no benefit over using a Func<>, you should use a traditional method for clarity instead.

没︽人懂的悲伤 2024-12-08 06:33:15

在第一种情况(使用 Func)中,您不是编写方法,而是编写使用特定委托初始化的变量 Foo。您可以使用一级间接来更改 Foo 指向的内容。为了简化您的示例:

public static class Test {

    public static Func<int, int, int> Foo =
        (i1, i2) =>
            i1 + i2;

    public static int Foo2(int i1, int i2)
    {
        return i1 + i2;
    }
}

让我们测试一下:

int a = Test.Foo(2,3);
int b = Test.Foo2(2,3);

Console.WriteLine("{0}, {1}",a,b); // 5, 5, all seems good, they're both sums

    //... but wait... now you can do this:
Test.Foo = (x,y) => x * y; //reassigning Foo
int c = Test.Foo(2,3);
Console.WriteLine("{0}",c); // 6 

因此,如果您使用这种间接级别,则 Func 方法是有意义的。但是,如果您不使用它,则说明您引入了过多的间接级别,这会影响性能、代码传达其意图的程度以及程序的正确性(因为您的方法现在可以切换为另一种方法)在运行时做一些不同的事情)

In the first case (with Func), you're not writing a method, but a variable Foo that you initialize with a specific delegate. You have one level of indirection that you can use to change what Foo points to. To simplify your example:

public static class Test {

    public static Func<int, int, int> Foo =
        (i1, i2) =>
            i1 + i2;

    public static int Foo2(int i1, int i2)
    {
        return i1 + i2;
    }
}

let's test:

int a = Test.Foo(2,3);
int b = Test.Foo2(2,3);

Console.WriteLine("{0}, {1}",a,b); // 5, 5, all seems good, they're both sums

    //... but wait... now you can do this:
Test.Foo = (x,y) => x * y; //reassigning Foo
int c = Test.Foo(2,3);
Console.WriteLine("{0}",c); // 6 

so, if you are usign this level of indirection, the Func approach makes sense. But if you're not using it, you have introduced one level of indirection too many, with impact on performance, on how well your code communicates its intent and on the correctness of your program (since your method can now be switched for another that does something different at runtime)

浪漫人生路 2024-12-08 06:33:15

理想情况下,如果总是只有一个 Func 定义,您就不会想创建一个 Func ..您不必要地增加了代码的复杂性和可读性,从而影响了可维护性..

如果您有充分的理由像您创建的那样使用它基于某些条件动态地调用 Func,然后使用 Func<>是有道理的..

另外看看Action。这是我阅读的一篇博客,解释何时使用什么: http://simpleprogrammer.com/2010/09/24/explaining-what-action-and-func-are/

ideally you wouldnt wanna create a Func if there is just going to be one definition of it always.. you are unnecessarily increasing the complexity and readability of the code and thus affecting the maintainability..

if you have strong reasons to use it like you create Func dynamically based on certain conditions then using Func<> is justified..

Also take a look at Action. here is a blog that I read to explain when to use what: http://simpleprogrammer.com/2010/09/24/explaining-what-action-and-func-are/

用心笑 2024-12-08 06:33:15

从“学习书”的角度来看,它应该是相同的,但

  • 性能影响很小,因为 lambdas/委托比具有通用名称的方法参数慢一点
  • (例如 arg1、arg2) code>)
  • Intellisense 通常无法提供文档工具提示
  • 定义为 lambda 字段的方法无法引入新的泛型参数
  • 影响可读性

From the "learning book" perspective it should be the same, but

  • small performance impact, because lambdas/delegates are little-bit slower than methods
  • parameters have generic names (e.g. arg1, arg2)
  • Intellisense is generally not able to provide documentation tooltips
  • Methods defined as lambda fields cannot introduce new generic parameters
  • readability impact
憧憬巴黎街头的黎明 2024-12-08 06:33:15

除了可读性下降之外,我认为没有任何其他危害。不确定代码如何编译,但在第一个版本中,您只是使用委托定义函数。我想你还可以执行以下操作:

private static List<T> Foo(int i1, int i2, DBContext dbc)
{
    i1 != 0 ? return dbc.Bar(i2) : return new List<T> { /*some default values ...*/ };
}

private static Func<int, int, DBContext, List<T>> Foo2 = Foo;

Apart from the readablity downgrade I don't think there's any other harm. Not sure about how the code compiles, but on the first version you are just defining the function using a delegate. I suppose you could also do the following:

private static List<T> Foo(int i1, int i2, DBContext dbc)
{
    i1 != 0 ? return dbc.Bar(i2) : return new List<T> { /*some default values ...*/ };
}

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