ToLookup有多个键

有没有办法要求LINQ提供的.ToLookup函数有多个键?

我承认起初这似乎不直观,我期待没有实际的方法来做到这一点,但我希望有人知道一种方式。

我基本上希望能够通过两个值进行查找,例如stringint ,并使用这两个值检索对象。

  public class MyClass { public string StringProp {get;set;} public int IntProp {get;set;} public object MoreData {get;set;} } public class Main { public void Main() { HashSet set = new HashSet(); set.Add(new MyClass {StringProp = "a", IntProp = 1, MoreData = null}); set.Add(new MyClass {StringProp = "c", IntProp = 4, MoreData = new object()}); set.Add(new MyClass {StringProp = "a", IntProp = 2, MoreData = "upupdowndown"}); set.Add(new MyClass {StringProp = "c", IntProp = 1, MoreData = string.Empty}); set.Add(new MyClass {StringProp = "c", IntProp = 4, MoreData = string.Empty}); // Using 'var' because I don't know how this would be defined. // I recognize that this will not compile - but this is what I'm trying to do. var lookup = set.ToLookup(x => x.StringProp && x.IntProp) MyClass c = lookup["a", 1].First(); // Should return the first element IEnumerable list = lookup["c", 4]; // Should return the 2nd and last elements } } 

我会用Tuple这种事情:

 var lookup = set.ToLookup(x => Tuple.Create(x.StringProp, x.IntProp)); MyClass c = lookup[Tuple.Create("a", 1)].First(); IEnumerable list = lookup[Tuple.Create("c", 4)]; 

所以其他答案都是我想的,但每次想要从查找中获取值时创建元组或匿名类有点麻烦。 如果您可以将字符串和int粘贴到索引器中以获取值,那不是很好吗? 通过创建自己的类来使用索引器包装查找,您可以完全执行此操作。

 public class MyLookup { private ILookup, TOut> lookup; public MyLookup(IEnumerable source, Func> keySelector) { lookup = source.ToLookup(keySelector); } public IEnumerable this[T1 first, T2 second] { get { return lookup[Tuple.Create(first, second)]; } } //feel free to either expose the lookup directly, or add other methods to access the lookup } 

以下是使用它的示例:

 IEnumerable data = null; //TODO populate with real data var lookup = new MyLookup(data , item => Tuple.Create(item.StringProp, item.IntProp)); IEnumerable someValue = lookup["c", 4]; 

虽然不是你真正想要的,但会做得很好:

 var r = set.ToLookup(x => new { x.StringProp, x.IntProp }); var f = r[ new { StringProp = "a", IntProp = 1 } ].First();