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

本文关键字:调用 表达式 函数 任何 官方 方法 是否 | 更新日期: 2023-09-27 18:27:55

像这样:

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";
    })
};

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

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

对于真正的代码,让它成为一个函数...出于娱乐目的,C#等同于JavaScript IIFE比Select更直接:

var myObject = new MyClass()
{
   x =((Func<int>)(() => {return 2;}))(),...
我很

惊讶还没有人提到这一点,但你可以使用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
};

或者,如果要避免在任何地方指定返回类型(就像使用new Lazy<string>一样,因为构造函数不支持类型推断(,则可以实现一个简单的泛型方法,如下所示:

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

然后你可以这样打电话:

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";
    })
};

更新: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";
}

这里的关键是,GetX可以在与myObject共享相同作用域的相同方法中声明。

这是我的同事想出的:

var myObject = new { 
    x = new Func<int>(() => {return 2;})() 
};

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

出于某种原因,很难获得隐式类型的委托,但如果您为它编写自己的静态方法,这并非不可能。

public static class Func {
   public static Func<T> Create<T>(
      Func<T> func
   ) =>
     func;       
}
...
x = Func.Create(() => "result")();
x = Func.Create(() => {
   // complex logic to create a value
})();

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

public class MyClass
{
   public string x { get; private set; }
   public MyClass(Func<string> x = null)
    {
        if (x != null)
            this.x = x();
    }
}

用法如下:

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"

因此,这不是您要求的确切语法,但非常接近并跳过了 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;
    }
}

用法类似(只是调用工厂方法(:

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";
        }
);

编辑:嘿,当我们在它的时候。为什么不离开深端,使用单独的构建器并滥用隐式运算符呢!

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;
    }
}

用法如下:

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";
        }
};

所以现在语法是相同的只是您必须显式键入实例而不是使用 var .

也许不能完全回答这个问题,但是...我希望在 C# 中使用 IIFE 的一个原因是为在对象上调用的函数赋予更好的含义。在这个例子中,我想给出关于"Click"方法在测试代码中的特定上下文中做什么的含义(我不喜欢注释(。

以前。。。

lastLine.Click(); //click to begin editing line

后。。。

Action<IWebElement> clickToStartEditing = line => line.Click();
clickToStartEditing(lastLine);

后来我发现我可以简单地创建一个具有另一个名称的新方法......

Action clickToStartEditing = lastLine.Click;
clickToStartEditing(lastLine);

最后,简单地以更好的方式命名变量可以更好地解决问题(对我来说(

lastLineForEditing.Click();

这为我解决了一个 IIFE 问题,为方法名称赋予了意义。

你可以做:

global using static System.IIFE;
namespace System {
  public static class IIFE {
    public static T Scope<T>(Func<T> f) => f();
  }
}

然后:

var x = Scope(() => {
  var t1 = getVal();
  vat t2 = getVal2();
  return t1+t2;
});

IIFE的优点是t1和t2不会污染外部范围