Func 有何伟大之处? 代表?

发布于 2024-07-09 14:00:32 字数 582 浏览 14 评论 0原文

抱歉,如果这是基本的,但我正在尝试学习 .Net 3.5。

问题:Func<> 有什么很棒的地方吗? 是5个重载吗? 从它的外观来看,我仍然可以自己创建一个类似的代理,MyFunc<> 具有精确的 5 次重载甚至更多。

例如: public delegate TResult MyFunc() 和各种重载的组合......

当我试图理解 Func<> 时,这个想法就出现了。 委托并遇到以下场景:

Func<int,int> myDelegate = (y) => IsComposite(10);

这意味着委托具有一个 int 类型的参数和一个 int 类型的返回类型。 有五种变体(如果您通过智能感知查看重载)。 所以我猜我们可以有一个没有返回类型的委托?

那么我有理由说 Func<> 吗? 没什么了不起的,只是 .Net 框架中的一个示例,我们可以使用它,如果需要,可以创建自定义“func<>” 代表适合我们自己的需要?

谢谢,

Sorry if this is basic but I was trying to pick up on .Net 3.5.

Question: Is there anything great about Func<> and it's 5 overloads? From the looks of it, I can still create a similar delgate on my own say, MyFunc<> with the exact 5 overloads and even more.

eg: public delegate TResult MyFunc<TResult>() and a combo of various overloads...

The thought came up as I was trying to understand Func<> delegates and hit upon the following scenario:

Func<int,int> myDelegate = (y) => IsComposite(10);

This implies a delegate with one parameter of type int and a return type of type int. There are five variations (if you look at the overloads through intellisense). So I am guessing that we can have a delegate with no return type?

So am I justified in saying that Func<> is nothing great and just an example in the .Net framework that we can use and if needed, create custom "func<>" delegates to suit our own needs?

Thanks,

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

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

发布评论

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

评论(6

自此以后,行同陌路 2024-07-16 14:00:32

伟大之处在于建立共享语言以实现更好的沟通

不要为同一事物定义自己的委托类型(委托爆炸),而是使用框架提供的委托类型。 阅读您的代码的任何人都会立即掌握您想要完成的任务......最大限度地减少“这段代码实际上在做什么?”的时间。
因此,一旦我看到

  • Action = 某种只做某事且不返回任何输出的方法
  • Comparison = 某种比较相同类型的两个对象并返回 int 的方法指示顺序
  • 转换器 = 将 Obj A 转换为等效的 Obj B
  • EventHandler = 对某个对象引发的事件的响应/处理程序,以事件参数的形式给出一些输入
  • Func = 某种接受一些参数、计算某些内容并返回结果的方法
  • Predicate = 根据某些条件评估输入对象并将通过/失败状态返回为 bool

我不必深入挖掘除非这是我直接关心的领域。 因此,如果您觉得您需要的委托符合这些需求之一,请在推出自己的需求之前使用它们。

免责声明:我个人喜欢语言设计者的这一举动。

反驳:有时定义您的委托可能有助于更好地传达意图。 例如,System.Threading.ThreadStart 优于 System.Action。 所以这最终是一个判断。

The greatness lies in establishing shared language for better communication.

Instead of defining your own delegate types for the same thing (delegate explosion), use the ones provided by the framework. Anyone reading your code instantly grasps what you are trying to accomplish.. minimizes the time to 'what is this piece of code actually doing?'
So as soon as I see a

  • Action = some method that just does something and returns no output
  • Comparison = some method that compares two objects of the same type and returns an int to indicate order
  • Converter = transforms Obj A into equivalent Obj B
  • EventHandler = response/handler to an event raised by some object given some input in the form of an event argument
  • Func = some method that takes some parameters, computes something and returns a result
  • Predicate = evaluate input object against some criteria and return pass/fail status as bool

I don't have to dig deeper than that unless it is my immediate area of concern. So if you feel the delegate you need fits one of these needs, use them before rolling your own.

Disclaimer: Personally I like this move by the language designers.

Counter-argument : Sometimes defining your delegate may help communicate intent better. e.g. System.Threading.ThreadStart over System.Action. So it’s a judgment call in the end.

眉黛浅 2024-07-16 14:00:32

Func 委托系列(及其无返回类型的表兄弟 Action)并不比您在 .NET 框架中找到的其他任何东西都要强大。 它们只是为了重复使用,因此您不必重新定义它们。 它们具有类型参数来保持通用性。 例如,Func与 System.Predicate相同 代表。 它们最初是为 LINQ 设计的。

您应该能够仅将内置 Func 委托用于接受最多 4 个参数的任何返回值方法,而不是为此目的定义自己的委托,除非您希望名称反映您的名称意图,这很酷。

您绝对需要定义委托类型的情况包括接受 4 个以上参数的方法、带有 outrefparams 参数的方法,或递归方法签名(例如,委托 Foo Foo(Foo f))。

The Func family of delegates (and their return-type-less cousins, Action) are not any greater than anything else you'd find in the .NET framework. They're just there for re-use so you don't have to redefine them. They have type parameters to keep things generic. E.g., a Func<T0,bool> is the same as a System.Predicate<T> delegate. They were originally designed for LINQ.

You should be able to just use the built-in Func delegate for any value-returning method that accepts up to 4 arguments instead of defining your own delegate for such a purpose unless you want the name to reflect your intention, which is cool.

Cases where you would absolutely need to define your delegate types include methods that accept more than 4 arguments, methods with out, ref, or params parameters, or recursive method signatures (e.g., delegate Foo Foo(Foo f)).

〆一缕阳光ご 2024-07-16 14:00:32

除了 Marxidad 的正确答案之外:

  • 值得注意的是 Func 的相关家族,Action 委托。 同样,这些是由类型参数数量重载的类型,但声明为返回 void。
  • 如果您想在 .NET 2.0 项目中使用 Func/Action,但以后有一个简单的升级途径,您可以从我的 版本比较页面。 如果您在 System 命名空间中声明它们,那么您只需稍后删除声明即可进行升级 - 但随后您将无法(轻松)在 .NET 3.5 中构建相同的代码删除声明。

In addition to Marxidad's correct answer:

  • It's worth being aware of Func's related family, the Action delegates. Again, these are types overloaded by the number of type parameters, but declared to return void.
  • If you want to use Func/Action in a .NET 2.0 project but with a simple route to upgrading later on, you can cut and paste the declarations from my version comparison page. If you declare them in the System namespace then you'll be able to upgrade just by removing the declarations later - but then you won't be able to (easily) build the same code in .NET 3.5 without removing the declarations.
遗失的美好 2024-07-16 14:00:32

解耦依赖性和不正当的联系是让它变得伟大的一个独特之处。 其他一切都可以争论并声称可以通过某种本土方式实现。

我一直在用旧的、笨重的库重构稍微复杂的系统,但由于无法打破编译时依赖性而受阻 - 因为命名委托潜伏在“另一边”。 所有程序集加载和反射都没有帮助 - 编译器将拒绝将 delegate() {...} 强制转换为对象,并且无论您做什么来平息它都会在另一边失败。

在编译时结构化的委托类型比较在之后变成名义上的(加载、调用)。 当您考虑“我亲爱的库将永远被每个人使用”时,这似乎没问题,但它无法扩展到甚至稍微复杂的系统。 有趣<> 模板将一定程度的结构等效带回名义打字的世界。 这是您通过推出自己的产品无法实现的。

示例 - 转换:

class Session ( 
    public delegate string CleanBody();    // tying you up and you don't see it :-)
    public static void Execute(string name, string q, CleanBody body) ... 

为:

    public static void Execute(string name, string q, Func<string> body)

允许完全独立的代码进行反射调用,例如:

Type type = Type.GetType("Bla.Session, FooSessionDll", true); 
MethodInfo methodInfo = type.GetMethod("Execute"); 

Func<string> d = delegate() { .....}  // see Ma - no tie-ups :-)
Object [] params = { "foo", "bar", d};
methodInfo.Invoke("Trial Execution :-)", params);

现有代码没有注意到差异,新代码不会获得依赖 - 地球和平:-)

Decoupling dependencies and unholy tie-ups is one singular thing that makes it great. Everything else one can debate and claim to be doable in some home-grown way.

I've been refactoring slightly more complex system with an old and heavy lib and got blocked on not being able to break compile time dependency - because of the named delegate lurking on "the other side". All assembly loading and reflection didn't help - compiler would refuse to just cast a delegate() {...} to object and whatever you do to pacify it would fail on the other side.

Delegate type comparison which is structural at compile time turns nominal after that (loading, invoking). That may seem OK while you are thinking in terms of "my darling lib is going to be used forever and by everyone" but it doesn't scale to even slightly more complex systems. Fun<> templates bring a degree of structural equivalence back into the world of nominal typing . That's the aspect you can't achieve by rolling out your own.

Example - converting:

class Session ( 
    public delegate string CleanBody();    // tying you up and you don't see it :-)
    public static void Execute(string name, string q, CleanBody body) ... 

to:

    public static void Execute(string name, string q, Func<string> body)

Allows completely independent code to do reflection invocation like:

Type type = Type.GetType("Bla.Session, FooSessionDll", true); 
MethodInfo methodInfo = type.GetMethod("Execute"); 

Func<string> d = delegate() { .....}  // see Ma - no tie-ups :-)
Object [] params = { "foo", "bar", d};
methodInfo.Invoke("Trial Execution :-)", params);

Existing code doesn't notice the difference, new code doesn't get dependence - peace on Earth :-)

江湖彼岸 2024-07-16 14:00:32

我喜欢委托的一件事是,它们让我可以在方法中声明方法,就像这样,当您想重用一段代码但只需要在该方法中使用它时,这很方便。 由于这里的目的是尽可能限制Func<>的范围。 派上用场了。

例如:

string FormatName(string pFirstName, string pLastName) {
    Func<string, string> MakeFirstUpper = (pText) => {
        return pText.Substring(0,1).ToUpper() + pText.Substring(1);
    };

    return MakeFirstUpper(pFirstName) + " " + MakeFirstUpper(pLastName);
}

当您可以使用推理时,它会更容易、更方便,如果您创建一个如下所示的辅助函数,则可以:

Func<T, TReturn> Lambda<T, TReturn>(Func<T, TReturn> pFunc) {
    return pFunc;
}

现在我可以在没有 Func<> 的情况下重写我的函数:

string FormatName(string pFirstName, string pLastName) {
    var MakeFirstUpper = Lambda((string pText) => {
        return pText.Substring(0,1).ToUpper() + pText.Substring(1);
    });

    return MakeFirstUpper(pFirstName) + " " + MakeFirstUpper(pLastName);
}

这​​是测试该方法的代码:

Console.WriteLine(FormatName("luis", "perez"));

One thing I like about delegates is that they let me declare methods within methods like so, this is handy when you want to reuse a piece of code but you only need it within that method. Since the purpose here is to limit the scope as much as possible Func<> comes in handy.

For example:

string FormatName(string pFirstName, string pLastName) {
    Func<string, string> MakeFirstUpper = (pText) => {
        return pText.Substring(0,1).ToUpper() + pText.Substring(1);
    };

    return MakeFirstUpper(pFirstName) + " " + MakeFirstUpper(pLastName);
}

It's even easier and more handy when you can use inference, which you can if you create a helper function like so:

Func<T, TReturn> Lambda<T, TReturn>(Func<T, TReturn> pFunc) {
    return pFunc;
}

Now I can rewrite my function without the Func<>:

string FormatName(string pFirstName, string pLastName) {
    var MakeFirstUpper = Lambda((string pText) => {
        return pText.Substring(0,1).ToUpper() + pText.Substring(1);
    });

    return MakeFirstUpper(pFirstName) + " " + MakeFirstUpper(pLastName);
}

Here's the code to test the method:

Console.WriteLine(FormatName("luis", "perez"));
简美 2024-07-16 14:00:32

虽然这是一个旧线程,但我必须添加该 func<> 和动作>> 还帮助我们使用协方差和反方差。

http://msdn.microsoft.com/en-us/library/dd465122.aspx

Though it is an old thread I had to add that func<> and action<> also help us use covariance and contra variance.

http://msdn.microsoft.com/en-us/library/dd465122.aspx

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