很容易lambda表达

时间:2011-10-25 07:33:37

标签: c# .net linq lambda

Ciao大家, 我终于能够从.NET Framework 2.0切换到.NET Framework 4.0。

我正在尝试获得有关lambda表达式和LINQ的一些经验。

是否可以翻译:

for (int cont = 0;cont < args.Length; cont++)
    Console.WriteLine("#" + cont + " " + "<" + args + ">");

进入单行lambda表达式,或者使用LINQ,甚至其他一些costruct我都不知道? 提前谢谢。

8 个答案:

答案 0 :(得分:6)

LINQ操作不应该有副作用或执行操作。它们只应用于IEnumerable<T>另一个IEnumerable<T>(或IQueryable<T>另一个IQueryable<T>IEnumerable<T>)(或者如果聚合,请{ {1}},.Max ...单个结果)

请阅读http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

(请注意,这个问题在SO上提出了很多问题...例如我在这里回复ToList().ForEach in Linq,并看到类似问题的解决方案)

现在,如果你讨厌自己,你可以这样做:

.All

我们正在使用strs.Select((p, index) => { Console.WriteLine("#" + index + " " + "<" + p + ">"); return true; }).All(p => p); 来“实现”.All(p => p)操作。这是因为Select是“懒惰的”,如果没有人循环它将不会被执行。

从技术上讲,你甚至可以尝试对它进行一些模糊处理:

Select

strs.Select((p, index) => { Console.WriteLine("#" + index + " " + "<" + p + ">"); return false; }).Any(p => p); 检查所有元素是否为All,如果其中一个元素为true则停止,因此必须循环所有元素(因为我们始终false )。return true;(如书面所示)检查至少有一个元素是Any然后停止(但我们所有的元素都是true,因为我们false所以return false;将循环所有元素)

现在......这些技术优于使用Any的优势在于我们不会将ToList“复制”到Array只是为了使用“错误”方法List<T>。如果List<T>的{​​{1}}方法“错误”,将ForEach复制到List<T>只是为了使用它是双重错误的。

答案 1 :(得分:4)

你必须先了解一些事情。 LINQ是一个功能样式的API。它的主要目的是提供一种简单而简洁的方法来操作序列。

您的代码可以使用LINQ编写,但这是不可取的:将内容写入流(例如控制台)最好以命令式方式完成,并且您的请求有点金锤。 / p>

答案 2 :(得分:3)

我不知道你为什么要这样,但是:

   args.ToList().ForEach(i => Console.WriteLine("#{0} <{1}>",
        args.ToList().IndexOf(i),
        i));

我想你确实要输出项目本身,而不是每行输出整个列表。

我已经使输出结构更好了。

IMO:您的原始代码更快更容易阅读。

答案 3 :(得分:1)

将它转换为lambda表达式是微不足道的,没用。

Action doLoop = ()=>{for (int cont = 0;cont < args.Length; cont++)
    Console.WriteLine("#" + cont + " " + "<" + args + ">");}

但是如果你想用linq替换循环,这可能是一个坏主意。 Linq专为无副作用代码而设计,Console.WriteLine是副作用。

如果您想使用linq,但仍然可以保留Console.WriteLine来电:

foreach(string s in Enumerable.Range(0,args.Length).Select("#" + cont + " " + "<" + args + ">"))
    Console.WriteLine(s);

有可能滥用Select来完全消除循环,但这太难看了,不能在这里发布。

许多人定义了一个ForEach扩展方法,代码变为:

Enumerable.Range(0,args.Count).ForEach(()=>Console.WriteLine("#" + cont + " " + "<" + args + ">"));

但我不喜欢这种风格。

答案 4 :(得分:1)

我希望这些链接可以帮助您了解和学习Lambdas和Linq。

MSDN Lambda Expressions

101 LINQ Examples

答案 5 :(得分:1)

这将完全符合您的要求:

    args
        .Select((x, n) => String.Format("#{0} <{1}>", n, args))
        .ToList()
        .ForEach(Console.WriteLine);

它产生的代码与您的代码相同:

#0 <System.String[]>
#1 <System.String[]>
#2 <System.String[]>

我猜你想要更像这样的东西:

var args = new [] { "Apple", "Banana", "Cherry", };

args
    .Select((x, n) => String.Format("#{0} <{1}>", n, x))
    .ToList()
    .ForEach(Console.WriteLine);

产生:

#0 <Apple>
#1 <Banana>
#2 <Cherry>

答案 6 :(得分:0)

假设这样的事情:

string[] args = new string[] { "a", "pippo", "c" };

你可以试试这个:

args.ToList().ForEach(
    p => Console.WriteLine(
        String.Format("# {0} <{1}>", p, args.Length)));

答案 7 :(得分:-1)

你的args必须是一个数组:

Array.ForEach(args, s => { Console.WriteLine("#" + Array.IndexOf(args, s) + " " + "<" + args + ">"); });