我有List<Email>()
,我的Email
对象如下所示:
public class Email
{
public string EmailAddress { get; set; }
public bool IsPrimary { get; set; }
}
当我添加一个设置为主要的新电子邮件地址时,我想将所有其他地址设置为非主要。我目前使用foreach
处理此问题。我可以使用LINQ
处理此问题吗?
我目前的代码是:
foreach (var item in emails)
{
if(item.EmailAddress.ToLower() != newEmailAddress.ToLower() && item.IsPrimary)
item.IsPrimary = false;
}
答案 0 :(得分:1)
Linq查询集合,它不会修改它们。 linq将发挥作用的这个等式中唯一的位置实际上是将它作为枚举的一部分 - 过滤你重复的集合,而不是在其中执行if
语句。
foreach (var item in emails.Where(e => e.IsPrimary && !e.EmailAddress.Equals(newEmailAddress, StringComparison.InvariantCultureIgnoreCase)))
{
item.IsPrimary = false;
}
编辑:我最初没有包含它,因为它不是LINQ而且问题是什么,但正如您在问题List<T>
的评论中所提到的那样一个ForEach方法。
看起来像这样:
emails.ForEach(item =>
{
item.IsPrimary = item.IsPrimary && item.EmailAddress.Equals(newEmailAddress, StringComparison.InvariantCultureIgnoreCase);
});
答案 1 :(得分:0)
LINQ用于查询而不是修改。话虽如此,有一个List.ForEach
运算符,但大部分时间都没有增加可读性。
话虽如此,我个人更喜欢没有副作用导致代码修改集合,但我并不反对修改集合中的对象。
在IEnumerable
上添加扩展方法以封装foreach
循环:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
foreach (var s in source)
action(s);
}
然后您可以按如下方式重新编写代码:
emails.Where(item => item.IsPrimary && !item.EmailAddress.Equals(newEmailAddress, StringComparison.InvariantCultureIgnoreCase))
.ForEach(item => item.IsPrimary = false);
(感谢@McAden更好的string
比较,我总是忘记。)
但是,既然你正在创造一个竞争条件,如果可行,我会建议你改变你的操作顺序:
// before adding newEmailAddress
emails[emails.FindIndex(item => item.IsPrimary)].IsPrimary = false; // add error handling if it is possible no `IsPrimary` exists.
// now assign the newEmailAddress and set that item.IsPrimary to true
答案 2 :(得分:-1)
你可以轻松地做到这一点,但你不应该因为没有人会期望LINQ代码来修改集合中的项目。
emails
.Where(item =>
(item.EmailAddress.ToLower() != newEmailAddress.ToLower() && item.IsPrimary)
.Select(item => { item.IsPrimary = false; return true;})
.All();
请注意,由于LINQ查询实际上是在枚举结果时执行的,因此您需要实际枚举结果的内容。即.All()
致电。
编写此代码后会发生什么 - 有人(或者你在一周之内)在最后删除那个愚蠢而毫无意义的.All()
来电,事情会有所改变
好的,但修改不再发生,人们将花一天时间将其整理出来,然后使用一些单词来描述代码的作者。不要去那里。