是否有任何官方方法可以编写立即调用的函数表达式?

eli*_*472 19 c#

像这样的东西:

var myObject = new MyClass()
{
    x = " ".Select(y =>
    {
        //Do stuff..
        if (2 + 2 == 5)
            return "I like cookies";
        else if (2 + 2 == 3)
            return "I like muffins";
        //More conditions...
        else
            return "I'm a bitter old man";
    })
};
Run Code Online (Sandbox Code Playgroud)

我意识到Select并不打算以这种方式使用.但是,有什么其他方法可以做同样的事情?

Ale*_*kov 20

对于真正的代码使它成为一个函数...对于娱乐目的,C#相当于JavaScript IIFESelect以下更直接:

var myObject = new MyClass()
{
   x =((Func<int>)(() => {return 2;}))(),...
Run Code Online (Sandbox Code Playgroud)

  • 你可以使用 `new` 让它看起来更漂亮一点。`x = new Func&lt;int&gt;(() =&gt; 2)()`。不幸的是,它不能被隐式输入。 (2认同)
  • 实际上,您可以使用静态方法使其隐式类型化。`x = Func.Create(() =&gt; 2)();` (2认同)

p.s*_*w.g 13

我很惊讶没人提到这个,但你可以使用这个Lazy<T>课:

var myObject = new MyClass()
{
    x = new Lazy<string>(() =>
    {
        //Do stuff..
        if (2 + 2 == 5)
            return "I like cookies";
        else if (2 + 2 == 3)
            return "I like muffins";
        //More conditions...
        else
            return "I'm a bitter old man";
    }).Value // <-- Evaluate the function here
};
Run Code Online (Sandbox Code Playgroud)

或者,如果您想避免必须在任何地方指定返回类型(new Lazy<string>因为构造函数不支持类型推断),您可以实现这样的简单泛型方法:

public static T Eval<T>(Func<T> func)
{
    return func();
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样打电话:

var myObject = new MyClass()
{
    x = Eval(() =>
    {
        //Do stuff..
        if (2 + 2 == 5)
            return "I like cookies";
        else if (2 + 2 == 3)
            return "I like muffins";
        //More conditions...
        else
            return "I'm a bitter old man";
    })
};
Run Code Online (Sandbox Code Playgroud)

更新:C#7引入了本地功能.这些不是真正的 IFFE,但它们可以解决各种相关问题.例如:

var myObject = new MyClass()
{
    x = GetX()
};

string GetX() {
    //Do stuff..
    if (2 + 2 == 5)
        return "I like cookies";
    else if (2 + 2 == 3)
        return "I like muffins";
    //More conditions...
    else
        return "I'm a bitter old man";
}
Run Code Online (Sandbox Code Playgroud)

这里的关键是GetX可以在相同的方法中声明与myObject共享相同的范围.


eli*_*472 6

这是我的同事的想法:

var myObject = new { 
    x = new Func<int>(() => {return 2;})() 
};
Run Code Online (Sandbox Code Playgroud)

请注意,这是基于阿列克谢的回答。

  • @MEMark我认为它不太忙,因为它需要跟踪的括号较少。这使得它对我来说更具可读性。回头看看,我猜保存的四个括号与要求“new”丢失的四个字符匹配。因此 `new Func&lt;int&gt;(() =&gt; 2)()` 和 `((Func&lt;int&gt;)(() =&gt; 2))()` 的长度都是 24 个字符。我仍然认为 `new` 语法比使用另外两对括号的语法更清晰。 (2认同)

Chr*_*air 5

虽然肯定不是 "官方",但您可以在构造函数中使用可选的命名参数或单独的工厂/构建器方法:

public class MyClass
{
   public string x { get; private set; }

   public MyClass(Func<string> x = null)
    {
        if (x != null)
            this.x = x();
    }
}
Run Code Online (Sandbox Code Playgroud)

用法如下:

var myClass = new MyClass(
        x: () =>
            {
                //Do stuff..
                if (2 + 2 == 5)
                    return "I like cookies";
                else if (2 + 2 == 3)
                    return "I like muffins";
                //More conditions...
                else
                    return "I'm a bitter old man";
            }
    );

    Console.WriteLine(myClass.x); //"I'm a bitter old man"
Run Code Online (Sandbox Code Playgroud)

所以,这不是你要求的确切语法,但非常接近并且跳过了LINQ的怪异.

那就是说,我不喜欢它.只是提供它作为思考的食物.:)


编辑:我想我会添加一个工厂方法样式,因为你在一个你不能(或不想)改变它的构造函数的类上使用它是合理的:

public static class MyFactory
{
    public static MyClass CreateMyClass(Func<string> x = null)
    {
        var myClass = new MyClass()

        if (x != null)
                myClass.x = x();

        return myClass;
    }
}
Run Code Online (Sandbox Code Playgroud)

具有类似的用法(只需调用工厂方法):

var myClass = MyFactory.CreateMyClass(
    x: () =>
        {
            //Do stuff..
            if (2 + 2 == 5)
                return "I like cookies";
            else if (2 + 2 == 3)
                return "I like muffins";
            //More conditions...
            else
                return "I'm a bitter old man";
        }
);
Run Code Online (Sandbox Code Playgroud)

编辑:嘿,我们在这里.为什么不离开深层并使用单独的构建器和滥用隐式运算符来执行此操作!

public class MyClassBuilder
{
    public Func<string> x { get; set; }

    public static implicit operator MyClass(MyClassBuilder builder)
    {
        var myClass = new MyClass();

        if (builder.x != null)
            myClass.x = builder.x();

        return myClass;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用方式如下:

MyClass myClass = new MyClassBuilder
{
    x = () =>
        {
            //Do stuff..
            if (2 + 2 == 5)
                return "I like cookies";
            else if (2 + 2 == 3)
                return "I like muffins";
            //More conditions...
            else
                return "I'm a bitter old man";
        }
};
Run Code Online (Sandbox Code Playgroud)

所以现在语法是相同的,除了你必须明确键入你的实例而不是使用var.


Dav*_*eau 5

获取隐式类型委托可能很棘手,但如果您为其编写自己的静态方法,它就可以工作。

您可以创建一个隐式类型函数,如下所示:

public static class Func {
   public static Func<T> Create<T>(
      Func<T> func
   ) =>
     func;       
}

...

var x = Func.Create(() => "result")();
Assert.AreEqual("result", x);

var x = Func.Create(() => {
   // complex logic to create a value
})();
Run Code Online (Sandbox Code Playgroud)

您还可以编写一个来立即计算函数,然后您不需要手动执行此操作:

public static class Func {
   public static T Eval<T>(
      Func<T> func
   ) =>
      func();
}

...

var x = Func.Eval(() => 5);
Assert.AreEqual(5, x);
Run Code Online (Sandbox Code Playgroud)