c# 延迟评估和返回值

Posted

技术标签:

【中文标题】c# 延迟评估和返回值【英文标题】:c# deferred evaluation and returned values 【发布时间】:2015-11-12 10:41:12 【问题描述】:

考虑到下面的示例,我很困惑为什么第一个示例的结果是 4, 8, 6 而第二个示例的结果是 4, 8, 3 ?对我来说,在第一个例子中,只有 succ(3) 和 dub(4) 被评估,y 应该是 3?有人可以帮忙解释它是如何工作的吗?非常感谢!

示例一:

public class Hello 
   public static void Main(string[] args) 
     int y = 0;
     Func<int,bool> even = (n) =>  return n%2 == 0; ; 
     Func<int,int> dub = (n) =>  y += 2; return n + n; ;
     Func<int,int> succ = (n) =>  y += 1; return n + 1; ;

     Func<bool, int, int, int> if1 = (c, t, f) => c? t: f;

     y = 0;
     var a1 = if1(even(3), dub(3), succ(3));
     var a2 = if1(even(4), dub(4), succ(4)); 
     Console.WriteLine("0 1 2", a1, a2, y);   
   
 

第二个例子:

public class Hello 
public static void Main(string[] args) 
  int y = 0;
  Func<int,bool> even = (n) =>  return n%2 == 0; ; 
  Func<int,int> dub = (n) =>  y += 2; return n + n; ;
  Func<int,int> succ = (n) =>  y += 1; return n + 1; ;

  Func<Func<int,bool>, Func<int,int>, Func<int,int>, Func<int,int>> if2 = (c, t, f) => (n) =>  if (c(n)) return t(n); else return f(n); ;

   y = 0;
   Func<int,int> x = if2(even, dub, succ); 
   var c1 = x(3);
   var c2 = x(4);
   Console.WriteLine("0 1 2", c1, c2, y);
 

【问题讨论】:

您是否尝试过使用调试器单步执行?继续按 F11 你就会得到答案:-) 【参考方案1】:

你混淆了两个不同的东西:

条件运算符 方法参数

所有方法参数在方法被调用之前被评估,即使它们在方法内部最终没有被使用。

因此,您在方法内部使用条件运算符这一事实与参数无关,它们都被评估了。

所以这个电话:

var a1 = if1(even(3), dub(3), succ(3));

将评估以下所有内容:

even(3) dub(3) succ(3)

在实际调用方法之前。如果您不是直接返回结果,而是返回了一个可以调用以获得结果的方法,那么您将拥有真正的延迟代码(在这种情况下),但我敢说代码会开始看起来非常难看。

                                   v---v
Func<int, Func<int>> dub = (n) =>  () =>  y += 2; return n + n; ;
Func<int, Func<int>> succ = (n) => () =>  y += 1; return n + 1; ;
Func<bool, Func<int>, Func<int>, int> if1 = (c, t, f) => c ? t() : f();
           ^-------------------^                              ^^    ^^

此外,正如@atlaste 在对您的问题的评论中所说,调试将揭示其工作原理,您会看到在进入if1 之前,您将逐步完成所有其他方法。

【讨论】:

它称为条件运算符。 谢谢!我现在没有调试器。我使用了 Dump() 但这并没有多大帮助。请问示例与示例一有何不同?对我来说,它们只是语法不同.. @user3735871 您的示例不会延迟调用参数函数,而 Lasse 的则可以。 Lasse 正在传递 函数,而您正在传递函数的返回值 - 这意味着他可以随意评估函数,而在您的情况下,必须先评估它们,然后再将它们的返回值传递给if1 函数。当调用 Lasse 的if1 时,你会做类似if1(even(3), () =&gt; dub(3), () =&gt; succ(3)) 的事情——注意包装函数。您可能还想将第一个参数更改为 Func&lt;bool&gt;,但由于 even 是纯的,所以没关系。 @Luaan 谢谢!你的意思是在上面的例子中,因为它在if2 处传递函数,所以在var c1 =x(3) 处,只有一个函数(在这种情况下是succ)会被评估? @user3735871 是的,因为您传递的是函数本身,而不是它的返回值。函数的评估仅在您执行 t() 时发生 - 就像任何其他方法调用一样。

以上是关于c# 延迟评估和返回值的主要内容,如果未能解决你的问题,请参考以下文章

制作python程序,直到Twisted延迟返回值

Android - 使用 WebView 评估 javascript 字符串并返回值

C#获取存储过程返回值和输出参数值的方法

按值返回值而不等待所有值返回异步 C#

SQL返回值 C#语言

C#函数返回两个值[重复]