2015-08-19 4 views
3

Учитывая приведенные ниже примеры, я смущен тем, почему результат для первого примера равен 4, 8, 6, а второй - 4, 8, 3? Для меня в первом примере оцениваются только succ (3) и dub (4), а y должно быть 3? Кто-нибудь может помочь объяснить, как это работает? Большое спасибо!C# отложенная оценка и возвращаемые значения

Пример один:

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); 
} 
} 
+0

Вы пробовали пройти через него с помощью отладчика? Продолжайте нажимать F11, и вы получите ответ :-) – atlaste

ответ

5

Вы путаете две разные вещи:

  • Условный оператор
  • аргументы Метод

Все аргументы метода оцениваются до вызова метода, даже если они внутри метода не используются.

Так что факт, что вы используете условный оператор внутри, метод не имеет отношения к аргументам, все они оцениваются.

Так этот вызов:

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 вы бы пройти через все другие методы.

+0

Его называют условным оператором. –

+0

Спасибо! На данный момент у меня нет отладчика. Я использовал Dump(), но это мало помогает. Могу ли я спросить, как пример отличается от примера один? Для меня это только другой синтаксис. – user3735871

+1

@ user3735871 В вашем примере не откладывается вызов функций аргумента, в то время как Lasse's делает. Lasse передает * функцию *, в то время как вы передаете возвращаемое значение функции - это означает, что он может оценивать функции по желанию, в то время как в вашем случае они должны быть оценены до передачи их возвращаемых значений в функцию 'if1' , При вызове 'if1' Lasse вы делаете что-то вроде' if1 (even (3),() => dub (3),() => succ (3)) '- обратите внимание на функцию обертывания. Вы также можете изменить первый аргумент на 'Func ', но так как 'even' является чистым, это не имеет значения. – Luaan

Смежные вопросы