简体   繁体   English

在c#中,为什么lambda不能有扩展?

[英]In c#, why can't lambdas have extensions?

In Unity, here's a category in c#, 在Unity中,这是c#中的一个类别,

public static class HandyExtensions
{
public static IEnumerator Tweeng( this System.Action<float> v, float d )
    {
    while (..)
        {
        ..
        v( 13f*t );
        yield return null;
        }
    v(13f);
    }

Compiles fine! 编译好!

But if you try to use it, 但是如果你试着用它,

yield return StartCoroutine(
            ( (x)=>laser=x ).Tweeng(3.141f)
        );

this saddening error appears: 出现这种令人悲伤的错误

Assets/scripts/...cs(116,34): error CS0023: The .' operator cannot be applied to operand of type 资产/脚本/ ... cs(116,34):错误CS0023:The .' operator cannot be applied to operand of type .' operator cannot be applied to operand of type anonymous method' .' operator cannot be applied to operand of type匿名方法.' operator cannot be applied to operand of type '

I have tears about this. 我为此感到泪流满面。

How could c# let us down? 怎么可能让我失望?

Surely there's a way to call "on" a lambda like that, for an extension? 当然有一种方法可以称之为“on”这样的lambda,用于扩展?

BTW the workaround is to go 3.14f.Tweeng((x)=>laser=x) but it's not as cool. BTW的解决方法是去3.14f.Tweeng((x)=>laser=x)但它并不酷。

I'm sorry this saddens you, but this choice was made deliberately by the language design team. 对不起,这让你感到很难过,但这个选择是由语言设计团队刻意做出的。 The code which evaluates whether a given extension method is valid requires that the receiver have a clear type, and lambda expressions do not have a type. 评估给定扩展方法是否有效的代码要求接收方具有clear类型,而lambda表达式没有类型。

There was some debate on this point, but ultimately it was decided that (1) the proposed feature is potentially confusing or error-prone if typeless expressions like lambdas, method groups and null literals get to be receivers of extension methods, and (2) the proposed feature is not at all necessary to make LINQ work. 关于这一点存在一些争论,但最终决定(1)如果像lambdas,方法组和null文字等无类表达式成为扩展方法的接收者,(1)所提出的特征可能容易混淆或容易出错,并且(2)所提出的功能根本不是使LINQ工作所必需的。 We were very constrained in our schedules when implementing C# 3 and anything that was not necessary to make LINQ work was cut. 在实施C#3时,我们的日程安排非常受限制,并且任何不必使LINQ工作的东西都被削减了。 It was much easier to design, implement and test the feature of "don't allow lambdas as receivers" than to have to consider all the potentially odd cases where a lambda, method group or null was being used as the receiver. 设计,实现和测试“不允许lambdas作为接收器”的特性要比考虑lambda,方法组或null被用作接收器的所有可能奇怪的情况要容易得多。

As others have said, you can simply cast the lambda, or put it in a variable and then use the variable as the receiver. 正如其他人所说,你可以简单地转换lambda,或者将它放在一个变量中,然后使用变量作为接收器。

Alternatively, as you note, you could consider using the float as the receiver in your specific example. 或者,正如您所注意到的,您可以考虑在特定示例中将float用作接收器。

Quell your tears fair Joe, let not despair drive you from your dream! 平息你的泪水乔,不要绝望地驱使你离开你的梦想! If you explicitly cast it, it should work. 如果你明确地施展它,它应该工作。 Try: 尝试:

yield return StartCoroutine(
        ((System.Action<float>)( (x)=>laser=x )).Tweeng(3.141f)
    );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM