c# - 对 3 个独立集合的单个 LINQ 查询

标签 c# linq c#-4.0

我有一个包含 3 个独立词典的对象。每个字典的值参数实现相同的接口(interface)。将 3 个词典合二为一并执行单个查询以使查询结果成为单个 IEnumerable 的最佳方法是什么?

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

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

关于如何实现我想要的,我有 2 种不同的想法,但我不确定是否有更好的方法来实现它?

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

由于每个对象都实现相同的接口(interface),是否可以在不转换的情况下对所有 3 个对象执行单个 LINQ 查询?

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

如果需要的话,这里大概介绍一下接口(interface)是如何实现的

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 个查找而不进行强制转换)。我在上面已经阐明了这一点。

最佳答案

您只需要在第一种方法中调用一个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);
}

现在这看起来已经非常接近第二种方法了——但不需要转换。

关于c# - 对 3 个独立集合的单个 LINQ 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9759858/

相关文章:

c# - 使用 Linq to SQL SELECT @@DBTS

c# - 在不使用魔术字符串的情况下将参数传递给 FakeItEasy-mock?

c# - linq的子查询方法不返回所有对象

C# Linq 按键组合多个序列

c# - DLR 的内存占用是多少?

c# - 林克 : query with three nested levels

.net - 尝试从网络位置加载程序集,这会导致程序集被沙箱化

c# - 使用C#将位图图像和音频流组合成视频的最佳方法

C# 绘制多条线

linq - 什么是 LINQ 中的投影,如 .Select()