c# - Linq Union 的问题行为?

标签 c# linq union enumeration

考虑以下示例:

    public IEnumerable<String> Test ()
    {
        IEnumerable<String> lexicalStrings = new List<String> { "test", "t" };
        IEnumerable<String> allLexicals = new List<String> { "test", "Test", "T", "t" };

        IEnumerable<String> lexicals = new List<String> ();
        foreach (String s in lexicalStrings)
            lexicals = lexicals.Union (allLexicals.Where (lexical => lexical == s));

        return lexicals;
    }

我希望它产生“test”、“t”作为输出,但它没有(输出只有“t”)。我不确定,但可能必须对延迟处理做些什么。有什么想法可以让它发挥作用或找到一个好的替代方案吗?

编辑:请注意,这只是一个简化的示例。 lexicalStringsallLexicals 在原代码中是不同的类型。所以我不能直接组合这些。

Edit2 要解决的问题看起来更像这样:

    public IEnumerable<Lexical> Test ()
    {
        IEnumerable<String> lexicalStrings = new List<String> { "test", "t" };
        IEnumerable<Lexical> allLexicals = new List<Lexical> { ... };

        IEnumerable<Lexical> lexicals = new List<Lexical> ();
        foreach (String s in lexicalStrings)
            lexicals = lexicals.Union (allLexicals.Where (lexical => lexical.Text == s));

        return lexicals;
    }

最佳答案

您正在使用错误的操作作为其他答案的解释。但有趣的是,为什么您的代码看起来不错,但仍然无法正常工作。

让我们稍微修改一下您的应用:

        IEnumerable<String> lexicalStrings = new List<String> { "test", "t" };
        IEnumerable<String> allLexicals = new List<String> { "test", "Test", "T", "t" };

        IEnumerable<String> lexicals = new List<String>();
        foreach (String s in lexicalStrings)
        {
            lexicals = lexicals.Union(
                allLexicals.Where(
                lexical =>
                {
                    Console.WriteLine(s);
                    return lexical == s;
                }
                )
            );
        }
        Console.WriteLine();
        foreach (var item in lexicals)
        {
        }

你期望什么输出?这是它:

t
t
t
t
t
t
t
t

很有趣,不是吗?

现在让我们再次修改它:

    IEnumerable<String> lexicalStrings = new List<String> { "test", "t" };
    IEnumerable<String> allLexicals = new List<String> { "test", "Test", "T", "t" };

    IEnumerable<String> lexicals = new List<String>();
    foreach (String s in lexicalStrings)
    {
        string ls = s;
        lexicals = lexicals.Union(
            allLexicals.Where(
            lexical =>
            {
                Console.WriteLine(ls);
                return lexical == ls;
            }
            )
        );
    }            
    foreach (var item in lexicals)
    {                
    }

现在输出和结果都很好:

test
test
test
test
t
t
t
t

为什么会这样?您使用闭包——在内部 lambda 中使用外部 var。由于您实际上并未迭代序列,因此 s 的当前值不会进入 lambda。 foreach 退出并且 s 的所有内部副本都保留上一次迭代的值。在内部变量的情况下,它们保存为每次迭代创建的值副本。这种冲突来自于 LINQ 的内在惰性。如果您在循环内执行类似 List.AddRange 的操作,结果会很好,因为 List.AddRange 会强制迭代。

关于c# - Linq Union 的问题行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2949768/

相关文章:

C# Linq GroupBy

.net - 最佳开源 LINQ 提供商

mysql - 连接来自两个不同表 MySQL 的所有行

php - mysql查询从多个中选择,按日期排序

c# - Aspose.Cells.CellsException - "You are using an evaluation copy and have opened files exceeding limitation"

c# - 需要使用Seed方法向映射表添加数据吗?

c# - 无边框形式 C# 中的自定义调整大小句柄

c# - ASP.NET Link 带按钮的回车键?

c# - 如何对一个数组使用 linq 的 group by 和 min 语句?

mysql - 带条件的多个表的SQL查询