非常简单的lambda表达式
本文关键字:表达式 lambda 简单 非常 | 更新日期: 2023-09-27 18:12:12
我想获得一些关于lambda表达式和LINQ的经验。
是否可以翻译成
for (int cont = 0;cont < args.Length; cont++)
Console.WriteLine("#" + cont + " " + "<" + args + ">");
变成单行lambda表达式,或者使用LINQ,或者甚至其他一些我不知道的结构?
LINQ操作不应该有副作用或执行操作。它们只能用于从IEnumerable<T>
产生另一个IEnumerable<T>
(或从IQueryable<T>
产生另一个IQueryable<T>
或IEnumerable<T>
)(或者如果聚合,如.Max
, .All
……)单个结果)
阅读例如http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx.
(注意这个问题是在……例如,阅读我在这里对list()的回复。在Linq中执行ForEach并查看类似问题的解决方案)
现在,如果你足够讨厌自己,你可以这样做:
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
相比,这些技术的优势在于,我们不会为了使用List<T>
的"错误"方法而将Array
"复制"到List<T>
。如果List<T>
的ForEach
方法是"错误的",将Array
复制到List
只是为了使用它是双重错误的。
有件事你必须先明白。LINQ是一个函数式风格的API。它的主要目的是提供一种简单而简洁的方法来操作序列。
您的代码可以使用LINQ编写,但这是不可取的:向流(例如控制台)编写内容最好使用命令式风格,并且您的请求带有金锤的味道。
我不知道你为什么想要这个,但是:
args.ToList().ForEach(i => Console.WriteLine("#{0} <{1}>",
args.ToList().IndexOf(i),
i));
我想你是想输出项目本身,而不是每行输出整个列表。
并且我已经使输出的构造稍微好一些。
我希望这个链接能帮助你理解和学习Lambdas和Linq。
MSDN Lambda表达式
101 LINQ示例
将其转换为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 + ">"));
但是我不喜欢这种风格。
这将完全符合您的要求:
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>
假设如下:
string[] args = new string[] { "a", "pippo", "c" };
你可以试试:
args.ToList().ForEach(
p => Console.WriteLine(
String.Format("# {0} <{1}>", p, args.Length)));
你的参数必须是一个数组:
Array.ForEach(args, s => { Console.WriteLine("#" + Array.IndexOf(args, s) + " " + "<" + args + ">"); });