非常简单的lambda表达式

本文关键字:表达式 lambda 简单 非常 | 更新日期: 2023-09-27 18:12:12

大家好!我终于可以从。net Framework 2.0切换到。net Framework 4.0了。

我想获得一些关于lambda表达式和LINQ的经验。

是否可以翻译成

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

变成单行lambda表达式,或者使用LINQ,或者甚至其他一些我不知道的结构?

非常简单的lambda表达式

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