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

2019-01-26 18:40发布

In Unity, here's a category in 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 typeanonymous method'

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?

BTW the workaround is to go 3.14f.Tweeng((x)=>laser=x) but it's not as cool.

标签: c# lambda
2条回答
虎瘦雄心在
2楼-- · 2019-01-26 18:47

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.

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. We were very constrained in our schedules when implementing C# 3 and anything that was not necessary to make LINQ work was cut. 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.

As others have said, you can simply cast the lambda, or put it in a variable and then use the variable as the receiver.

Alternatively, as you note, you could consider using the float as the receiver in your specific example.

查看更多
Fickle 薄情
3楼-- · 2019-01-26 19:01

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)
    );
查看更多
登录 后发表回答