C#范围运算符

tbi*_*hel 6 c# scope curly-braces

回到学校,我们写了一个编译器,其中花括号具有执行所有表达式的默认行为,并返回最后一个值...所以你可以这样写:

int foo = { printf("bar"); 1 };
Run Code Online (Sandbox Code Playgroud)

在C#中有相同的东西吗?例如,如果我想编写一个具有副作用的lambda函数.

关于lambda副作用的一点(仅仅是一个例子),如果有这个功能则更多...例如在lisp中,你有预测

Aar*_*ght 7

没有什么可以阻止你在lambda表达式中产生副作用.

Func<int> expr = () =>
{
    Console.WriteLine("bar");
    return 1;
};
int foo = expr();
Run Code Online (Sandbox Code Playgroud)


Tom*_*cek 7

原则上,Vlad的答案是正确的,您不需要事先将lambda函数声明为委托.

除此之外,C#中的情况并不那么简单,因为编译器无法确定语法lambda表达式是应该编译为委托(例如Func<int>)还是表达式树(例如Expression<Func<int>>),还可以是任何其他兼容的委托类型.因此,您需要创建委托:

int foo = new Func<int>(() => { 
  Console.WriteLine("bar"); return 1; })(); 
Run Code Online (Sandbox Code Playgroud)

您可以通过定义一个简单地返回委托然后调用该方法的方法来稍微简化代码 - C#编译器将自动推断委托类型:

static Func<R> Scope<R>(Func<R> f) { return f; }

// Compiler automatically compiles lambda function
// as delegate and infers the type arguments of 'Scope'
int foo = Scope(() => { Console.WriteLine("bar"); return 1; })(); 
Run Code Online (Sandbox Code Playgroud)

我同意这是一个不应该使用的丑陋技巧:-),但它是一个有趣的事实,它可以做到!


Vla*_*lad 5

int foo = (() => { printf("bar"); return 1; })();
Run Code Online (Sandbox Code Playgroud)

编辑:感谢建设性的批评,它应该是

int i = ((Func<int>)(() => { printf("bar"); return 1; }))();
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的答案 - 说,认真考虑不这样做. (5认同)
  • 你们可能想要在投票前实际检查代码是否编译.事实并非如此.-1. (2认同)