如何编写更复杂的LINQ查询

Dav*_*een 2 c# linq

假设我有:

public class Cluster
{
   List<Host>  HostList = new List<Host>();
}
public class Host
{
   List<VDisk> VDiskList = new List<VDisk>();
} 

public class VDisk
{
   public string Name {get; set}
}
Run Code Online (Sandbox Code Playgroud)

我需要具有给定名称的VDisk的Cluster对象中的所有主机.我可以用foreach做,但宁愿有LINQ查询.我尝试了一个SelectMany(),但它返回VDisk而不是Hosts.我是否需要实现自定义Comparer才能执行此操作?

这是我试过的:

Cluster CurrentCluster = new Cluster();

// add some hosts here

VDisk vdisk = new VDisk();
vdisk.Name="foo";
Run Code Online (Sandbox Code Playgroud)

所以现在我想要所有拥有名为"foo"的虚拟磁盘的主机

这将返回虚拟磁盘,而不是主机:

CurrentCluster.Hosts.SelectMany(h => h.VDisks.Where(v => v.Name == vdisk.Name));
Run Code Online (Sandbox Code Playgroud)

Dav*_*vid 7

SelectMany确实会将内部收藏品归还成一个大型收藏品.你希望你的谓词打开Hosts而不是打开VDisks,因为你要查找的是一个列表Hosts.

这可能有效:

CurrentCluster.Hosts.Where(h => h.VDisks.Any(v => v.Name == vdisk.Name));
Run Code Online (Sandbox Code Playgroud)

它基本上说,"返回任何VDisks符合条件的所有主机v.Name == vdisk.Name.

我也见过不懂的开发人员Any写这样的东西:

CurrentCluster.Hosts.Where(h => h.VDisks.Count(v => v.Name == vdisk.Name) > 0);
Run Code Online (Sandbox Code Playgroud)

有时我觉得后者有一定的可读性优势,如果有人认为这Count是一个比直觉更直观的名字Any.两者都应该做,我只是喜欢前者.

  • 根据`Name`中的内容,使用`v.Name.Equals(vDisk.Name,StringComparison.InvariantCultureIgnoreCase)可能会更好.@ David Count也会枚举整个集合,其中`Any`在第一个匹配的谓词上停止因此,使用它比使用Count可以有性能优势. (3认同)