Вы можете сделать это с помощью функций высшего порядка:
Func<Node, decimal> summer = null;
summer = node => node.Amount +
(node.Children == null ? 0m : node.Children.Sum(summer));
decimal total = summer(amounts);
Обратите внимание, что если вы можете гарантировать, что node.Children никогда не будет аннулирована, лето может быть проще:
summer = node => node.Amount + node.Children.Sum(summer);
В качестве альтернативы, вы можете использовать оператора нулевой коалесценции:
summer = node => node.Amount +
(node.Children ?? Enumerable.Empty<Node>()).Sum(summer);
Конечно, вы можете поместить это в отдельный вместо этого:
static decimal SumNodes(Node node)
{
return node.Amount +
(node.Children ?? Enumerable.Empty<Node>())
.Sum((Func<Node, decimal>)SumNodes);
}
Обратите внимание, что уродство объясняется двусмысленностью в преобразованиях групп методов. Группы методов не очень любят вывод типа.
, а затем позвоните SumNodes(amount)
. Много вариантов :)
Полный пример первой формы:
using System;
using System.Collections.Generic;
using System.Linq;
class Node
{
public decimal Amount;
public IEnumerable<Node> Children { get; set; }
}
public class Test
{
static void Main()
{
var amounts = new Node {
Amount = 10, Children = new[] {
new Node { Amount = 20 },
new Node { Amount = 30 }
}
};
Func<Node, decimal> summer = null;
summer = node => node.Amount +
(node.Children == null ? 0m : node.Children.Sum(summer));
decimal total = summer(amounts);
Console.WriteLine(total);
}
}
Я не уверен, что я назвал бы любой из них «простой» LINQ запрос, заметьте ...
Jon, я бы поднял это еще несколько раз, но SO не позволит мне. –
Строго говоря, это скорее «функция более высокого порядка», чем истинная «рекурсивная лямбда» ... –
Это было не так, пока я не исправил ее :) –