选择并在列表上进行搜索. [英] Select and ForEach on List<>

查看:71
本文介绍了选择并在列表上进行搜索.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对C#相当陌生,并试图使用lambda表达式.

I am quite new to C# and was trying to use lambda expressions.

我有一个对象列表.我想从列表中选择一个项目,然后对所选项目执行foreach操作.我知道我可以在不使用lambda表达式的情况下做到这一点,但想知道是否可以使用lambda表达式.

I am having a list of object. I would like to select item from the list and perform foreach operation on the selected items. I know i could do it without using lambda expression but wanted to if this was possible using lambda expression.

所以我试图达到类似的结果

So i was trying to achieve a similar result

        List<UserProfile> users = new List<UserProfile>();
       ..load users with list of users
        List<UserProfile> selecteditem = users.Where(i => i.UserName=="").ToList();
        foreach(UserProfile item in selecteditem)
        {
            item.UserName = "NA";
        }

有可能做

      users.Where(i => i.UserName=="").ToList().ForEach(i=>i.UserName="NA");

但不是这样

     users.select(i => i.UserName=="").ForEach(i=>i.UserName="NA");

有人可以解释这种行为吗?.

Can someone explain this behaviour..

推荐答案

让我们从这里开始:

我有一个对象列表.

I am having a list of object.

重要的是要理解,尽管准确,但该语句使C#程序员需要更多.什么样的物体?在.Net世界中,必须牢记您正在使用哪种特定类型的对象.在这种情况下,该类型为UserProfile.这似乎是一个附带问题,但它将很快与特定问题变得更加相关.您要说的是这样的:

It's important to understand that, while accurate, that statement leaves a c# programmer wanting more. What kind of object? In the .Net world, it pays to always keep in mind what specific type of object you are working with. In this case, that type is UserProfile. This may seem like a side issue, but it will become more relevant to the specific question very quickly. What you want to say instead is this:

我有一个UserProfile对象列表.

I have a list of UserProfile objects.

现在让我们看看您的两个表达式:

Now let's look at your two expressions:

users.Where(i => i.UserName ==").ToList().ForEach(i => i.UserName ="NA");

users.Where(i => i.UserName=="").ToList().ForEach(i=>i.UserName="NA");

users.Where(i => i.UserName ==").ForEach(i => i.UserName ="NA");

users.Where(i => i.UserName=="").ForEach(i=>i.UserName="NA");

区别(除了仅第一个编译或工作以外)是您需要调用.ToList()Where()函数的结果转换为List类型.现在,我们开始了解为什么为什么在使用.Net代码时总是要根据类型进行思考,因为您现在应该想知道,我使用的是哪种类型,然后?"我很高兴你问.

The difference (aside from that only the first compiles or works) is that you need to call .ToList() to convert the results of Where() function to a List type. Now we begin to see why it is that you want to always think in terms of types when working with .Net code, because it should now occur to you to wonder, "What type am I working with, then?" I'm glad you asked.

.Where()函数产生一个IEnumerable<T>类型,实际上它本身并不是一个完整的类型.这是一个接口,用于描述实现其合同的类型将能够执行的某些操作. IEnumerable接口一开始可能会令人困惑,但是要记住的重要一点是,它定义了可以与foreach循环一起使用的东西.那是唯一的目的. .Net中可以与foreach循环一起使用的所有内容:数组,列表,集合—它们几乎都实现了IEnumerable接口.您还可以循环进行其他操作.例如字符串.如今,只需将参数类型更改为IEnumerable,就可以使许多需要将List或Array作为参数的方法变得更加强大和灵活.

The .Where() function results in an IEnumerable<T> type, which is actually not a full type all by itself. It's an interface that describes certain things a type that implements it's contract will be able to do. The IEnumerable interface can be confusing at first, but the important thing to remember is that it defines something that you can use with a foreach loop. That is it's sole purpose. Anything in .Net that you can use with a foreach loop: arrays, lists, collections — they pretty much all implement the IEnumerable interface. There are other things you can loop over, as well. Strings, for example. Many methods you have today that require a List or Array as an argument can be made more powerful and flexible simply by changing that argument type to IEnumerable.

.Net还使创建基于状态机的迭代器(与此接口一起使用)变得容易.这对于创建本身不保存任何项目但知道如何以特定方式循环遍历其他集合中的项目的对象特别有用.例如,我可能会循环遍历大小为20的数组中的第3到第12个项目,或者可能按字母顺序遍历这些项目.这里重要的是,我可以执行此操作而无需复制或复制原件.这使得它在内存方面非常高效,并且其结构使您可以轻松地将不同的迭代器组合在一起以获得非常强大的结果.

.Net also makes it easy to create state machine-based iterators that will work with this interface. This is especially useful for creating objects that don't themselves hold any items, but do know how to loop over items in a different collection in a specific way. For example, I might loop over just items 3 through 12 in an array of size 20. Or might loop over the items in alphabetical order. The important thing here is that I can do this without needing to copy or duplicate the originals. This makes it very efficient in terms of memory, and it's structure in such a way that you can easily compose different iterators together to get very powerful results.

IEnumerable<T>类型特别重要,因为它是构成linq系统核心的两种类型之一(另一种是IQueryable).您可以使用的大多数.Where().Select().Any()等linq运算符都定义为IEnumerable的扩展名.

The IEnumerable<T> type is especially important, because it is one of two types (the other being IQueryable) that form the core of the linq system. Most of the .Where(), .Select(), .Any() etc linq operators you can use are defined as extensions to IEnumerable.

但是现在我们有了一个例外:ForEach().此方法不是IEnumerable的 not 部分.它直接定义为List<T>类型的一部分.因此,我们再次看到,重要的是要始终了解您使用的是哪种类型,包括构成完整语句的每个不同表达式的结果.

But now we come to an exception: ForEach(). This method is not part of IEnumerable. It is defined directly as part of the List<T> type. So, we see again that it's important to understand what type you are working with at all times, including the results of each of the different expressions that make up a complete statement.

为什么为什么不直接是IEnumerable的一部分也是有指导意义的.我相信答案在于linq系统从函数式编程世界中汲取了很多灵感.在函数式编程中,您希望具有仅做一件事且没有副作用的操作(函数).理想情况下,这些函数不会更改原始数据,而是返回新数据. ForEach()方法隐式地涉及创建会改变数据的不良副作用.这只是糟糕的功能风格.另外,ForEach()中断了方法链接,因为它不会返回新的IEnumerable.

It's also instructional to go into why this particular method is not part of IEnumerable directly. I believe the answer lies in the fact that the linq system takes a lot of inspiration from a the Functional Programming world. In functional programming, you want to have operations (functions) that do exactly one thing, with no side effects. Ideally, these functions will not alter the original data, but rather they will return new data. The ForEach() method is implicitly all about creating bad side effects that alter data. It's just bad functional style. Additionally, ForEach() breaks method chaining, in that it doesn't return a new IEnumerable.

这里还有另外一课要学习.让我们看看您的原始代码段:

There is one more lesson to learn here. Let's take a look at your original snippet:

List<UserProfile> users = new List<UserProfile>();
// ..load users with list of users
List<UserProfile> selecteditem = users.Where(i => i.UserName=="").ToList();
foreach(UserProfile item in selecteditem)
{
    item.UserName = "NA";
}

我前面提到了一些可以帮助您大大改善此代码的东西.还记得有关如何使IEnumerable项遍历集合而不重复的一点点吗?考虑一下如果您以这种方式编写该代码会发生什么,

I mentioned something earlier that should help you significantly improve this code. Remember that bit about how you can have IEnumerable items that loop over a collection, without duplicating it? Think about what happens if you wrote that code this way, instead:

List<UserProfile> users = new List<UserProfile>();
// ..load users with list of users
var selecteditem = users.Where(i => i.UserName=="");
foreach(UserProfile item in selecteditem)
{
    item.UserName = "NA";
}

我所做的只是删除了对.ToList()的调用,但是一切仍然可以进行.唯一更改的是我们避免了复制整个列表.这样可以使此代码更快 .在某些情况下,它可以使代码更快很多.注意事项:使用linq运算符方法时,通常最好避免尽可能地调用.ToArray().ToList(),这可能比您想像的要多得多.

All I did was remove the call to .ToList(), but everything will still work. The only thing that changed is we avoided needing to copy the entire list. That should make this code faster. In some circumstances, it can make the code a lot faster. Something to keep in mind: when working the with the linq operator methods, it's generally good to avoid calling .ToArray() or .ToList() whenever possible, and it's possible a lot more than you might think.

对于foreach() {...}.Foreach( ... ):前者仍然是完全合适的样式.

As for the foreach() {...} vs .Foreach( ... ): the former is still perfectly appropriate style.

这篇关于选择并在列表上进行搜索.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆