2012-03-18 44 views
3

我有一个包含3个单独字典的对象。每个字典的值参数实现相同的接口。将3个字典合并为一个并执行单个查询的最佳方法是什么,以便查询的结果将是单个IEnumerable?3个独立集合上的单个LINQ查询

下面是我试图完成的一个粗略的想法。我的DataSet对象包含3个字典,每个字典应该非常小(理论上有些可以包含多达100个元素,但除了最极端的情况下,它们总是小于20,通常为6或更少)。

GetAllId()方法的目的是检索每个字典的每个元素中的几个专用字段的Id,并将其作为单个IEnumerable返回。字典值对象都实现了IIdQueryable,它定义了一个方法,该方法将提取对象中所有需要的Id

我对如何实现我想要的有两种不同的想法,但我不确定是否有更好的方法来实现这一点?

public class DataSet 
{ 
    Dictionary<Int32, Foo> dict1; 
    Dictionary<CustomKey, Bar> dict2; 
    Dictionary<Int32, Boo> dict3; 

    public IEnumerable<Int32> GetAllId 
    { 
     // need to retrieve Id from dict1, dict2, and dict3. 
     // implementation ideas below 
    } 
} 

选项1

public IEnumerable<Int32> GetAllId 
{ 
    var q1 = dict.Values.SelectMany(g => g.GetId()); 
    var q2 = dict.Values.SelectMany(g => g.GetId()); 
    var q3 = dict.Values.SelectMany(g => g.GetId()); 

    return q1.Concat(q2).Concat(q3); 
} 

选项2

public IEnumerable<Int32> GetAllId 
{ 
    var c1 = dict1.Values.Cast<IIdQueryable>(); 
    var c2 = dict2.Values.Cast<IIdQueryable>(); 
    var c3 = dict2.Values.Cast<IIdQueryable>(); 

    var collection = c1.Concat(c2).Concat(c3); 

    return collection.SelectMany(g => g.GetId()); 
} 

方法#3

由于每个objec t实现相同的接口,是否可以在不投射的情况下对所有3个对象执行单个LINQ查询?

我个人更喜欢方法1,因为它不涉及任何东西,但我认为方法2似乎更具可读性。

如果需要它,这里的接口是如何实现的一个粗略的想法

public interface IIdQueryable 
{ 
    IEnumerable<Int32> GetId(); 
} 

public class Foo : IIdQueryable 
{ 
    public IEnumerable<Int32> GetId() 
    { 
     //returns Id of all elements in this object 
    } 
} 

public class Bar : IGuidQueryable 
{ 
    public IEnumerable<Int32> GetId() 
    { 
     //returns Id of all elements in this object 
    } 
} 

public class Boo : IGuidQueryable 
{ 
    public IEnumerable<Int32> GetId() 
    { 
     //returns Id of all elements in this object 
    } 
} 

编辑:

问题的标题是什么,我希望可以做的来源(即是在单个查询中进行全部3次查找而不投射)。我澄清了上述情况。

回答

2

你只需要在第一个方法调用SelectMany

public IEnumerable<Int32> GetAllId() 
{ 
    return dict1.Values 
       .Select(x => x.GetId()) 
       .Concat(dict2.Values.Select(x=> x.GetId())) 
       .Concat(dict3.Values.Select(x => x.GetId())) 
       .SelectMany(x => x); 
} 

个人而言,我不会管磁带了一起,虽然,有通过保持独立的查询和刚刚返回像串联不会影响性能你确实已经在第一个例子 - 它是更具可读性对我说:

public IEnumerable<Int32> GetAllId() 
{ 
    var q1 = dict1.Values.Select(g => g.GetId()); 
    var q2 = dict2.Values.Select(g => g.GetId()); 
    var q3 = dict3.Values.Select(g => g.GetId()); 

    return q1.Concat(q2) 
      .Concat(q3) 
      .SelectMany(x => x); 
} 

现在这个看起来相当接近已经第二种方法 - 但没有投需要。

+1

其实他在第一个例子中确实需要'SelectMany'。当你想要'IEnumerable '时,'Select'返回'IEnumerable 2012-03-18 16:55:49

+0

是的,我固定,因为,那是一个疏忽 – BrokenGlass 2012-03-18 16:56:25

+0

@BrokenGlass - 我从来没有处理.SelectMany()在我有一个选择,在哪里把它放在上下文中。是否有性能原因,为什么你建议移动它,因此它只被调用一次?或者你认为这只是让它更具可读性? – psubsee2003 2012-03-18 17:25:09