这样的事情:
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不打算以这种方式使用。但是,有什么其他方法可以做同样的事情吗?
答案 0 :(得分:19)
对于真实代码,使其成为一种功能......出于娱乐目的,等同于JavaScript IIFE的C#比Select
更直接:
var myObject = new MyClass()
{
x =((Func<int>)(() => {return 2;}))(),...
答案 1 :(得分: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
};
或者,如果您想避免必须在任何地方指定返回类型(与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介绍了local functions。这些不是真正的 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
共享相同范围的同一方法中声明。
答案 2 :(得分:6)
虽然当然不是“官方”,但可以在构造函数中使用可选的命名参数或单独的工厂/构建器方法:
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
。
答案 3 :(得分:4)
这是我的同事提出的:
var myObject = new {
x = new Func<int>(() => {return 2;})()
};
请注意,这是基于阿列克谢的回答。
答案 4 :(得分:1)
也许不是很回答这个问题,但是...我想要用C#进行IIFE的原因之一是要赋予在对象上调用的函数更好的含义。在此示例中,我想说明“点击”方法在测试代码中特定上下文中的作用(我不喜欢注释)。
之前...
lastLine.Click(); //click to begin editing line
之后...
Action<IWebElement> clickToStartEditing = line => line.Click();
clickToStartEditing(lastLine);
后来我发现我可以简单地用另一个名字创建一个新方法...
Action clickToStartEditing = lastLine.Click;
clickToStartEditing(lastLine);
最后简单地以更好的方式命名变量可以更好地解决问题(对我来说)
lastLineForEditing.Click();
这为我解决了IIFE问题,使方法名称具有含义。
答案 5 :(得分:1)
由于某种原因,获取隐式类型的委托确实很困难,但是如果您为其编写自己的静态方法,并不是没有可能。
public static class Func {
public static Func<T> Create<T>(
Func<T> pFunc
) =>
pFunc;
}
...
x = Func.Create(() => "result")();
x = Func.Create(() => {
// complex logic to create a value
})();