我想知道当需要来自多个记录的单个值时,是否有一些聪明的方法可以使用LINQ从可枚举中检索数据.
例如,假设您有一个拥有三个不同电话字段的人:
public class Person
{
public Phone HomePhone { get; set; }
public Phone WorkPhone { get; set; }
public Phone CellPhone { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
...但电话列表以标准化格式存储:
public enum PhoneType
{
Home, Work, Cell
}
public class Phone
{
public PhoneType Type { get; set; }
public string Number { get; set; }
}
static public IEnumerable<Phone> GetPhoneList()
{
yield return new Phone { Type = PhoneType.Home, Number = "8005551212" };
yield return new Phone { Type = PhoneType.Work, Number = "8005551313" };
yield return new Phone { Type = PhoneType.Cell, Number = "8005551414" };
}
Run Code Online (Sandbox Code Playgroud)
如果你需要填充Person,你可以写一个循环,并在一遍中获得你需要的一切:
public static Person GetPerson1()
{
var result = new Person();
foreach (var ph in GetPhoneList())
{
switch (ph.Type)
{
case PhoneType.Home: result.HomePhone = ph; break;
case PhoneType.Work: result.WorkPhone = ph; break;
case PhoneType.Cell: result.CellPhone = ph; break;
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
但是如果你想使用LINQ,似乎可能需要三次传递:
public static Person GetPerson2()
{
return new Person
{
HomePhone = GetPhoneList().Single( ph => ph.Type == PhoneType.Home ),
WorkPhone = GetPhoneList().Single( ph => ph.Type == PhoneType.Work ),
CellPhone = GetPhoneList().Single( ph => ph.Type == PhoneType.Cell )
};
}
Run Code Online (Sandbox Code Playgroud)
是否有一种聪明的方法可以使用LINQ通过枚举只传递一次来获取所有内容?
(我知道我可以使用字典或其他数据结构来解决这个特殊问题;这只是一个例子.)
小智 4
通常,您不能在 LINQ 中执行此操作。
如果您确实愿意,可以创建一个 Foreach 扩展方法并执行与您的GetPerson1方法相同的操作。
public static class Ext
{
public static void Foreach<T>(this IEnumerable<T> e, Action<T> action)
{
foreach (T item in e)
{
action(item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
进而
public static Person GetPerson2()
{
var p = new Person();
var pl = GetPhoneList();
pl.Foreach(ph =>
{
switch (ph.Type)
{
case PhoneType.Home: p.HomePhone = ph; break;
case PhoneType.Work: p.WorkPhone = ph; break;
case PhoneType.Cell: p.CellPhone = ph; break;
}
});
return p;
}
Run Code Online (Sandbox Code Playgroud)
但你真的不应该。LINQ 旨在对 IEnumerables 进行操作(逐项),并且 LINQ 函数应该没有副作用,而 foreach 循环和 Foreach 扩展方法只会产生副作用,从而更改 Person 对象的状态。
而且,除此之外,您需要一种“聪明的方式”这一事实应该表明这不是它应该使用的方式:)
Eric Lippert 写了一篇很棒的文章,其中包含更多详细信息:https ://blogs.msdn.microsoft.com/ericlippert/2009/05/18/foreach-vs-foreach/