【问题标题】:Not properly Grouping items in a collection with LINQ使用 LINQ 未正确对集合中的项目进行分组
【发布时间】:2013-11-23 17:28:45
【问题描述】:

我有一个方法尝试使用 SharpSVN 将 n 个文件添加到存储库。任何数量的这些文件都可能引发错误,我捕获了该错误,然后转到下一个文件并尝试添加它,依此类推。我想提醒用户 X 次,其中 X 是不同原因的数量。因此,如果我添加了 5 个文件,其中 3 个因一个原因而失败,而 2 个因其他原因而失败,我想呈现 2 个错误。如果它们都因相同的原因而失败,则为 1 个错误。五个不同的原因?提出 5 个错误。

我创建了一个类FileException,它有两个属性(Exception Ex,string FileName)并尝试实现一个集合,以便我可以将它分组到异常上。

    public void AddFiles(List<string> files)
    {
        var sb = new StringBuilder();
        var args = new SvnAddArgs {Depth = SvnDepth.Children};
        var exes = new Collection<FileException>();

        foreach (var file in files)
        {
            try
            {
                //only here for testing purposes described below
                if (file.Contains("png"))
                    throw new AccessViolationException();

                SVNClient.Add(file, args);
            }
            catch (Exception ex)
            {
                exes.Add(new FileException(ex, file));
            }
        }

        if (exes.Count > 1)
        {
            exes.GroupBy(s => s.Ex.GetType());
            Unique<Log>.Instance.AddExceptions(exes);
        }
        else if (exes.Count == 1)
            Unique<Log>.Instance.AddException(exes[0].Ex);
    }

    public void AddExceptions(Collection<FileException> e)
    {
        var sb = new StringBuilder();
        var ex = e[0].Ex;

        for(var i=0; i < e.Count;i++)
        {
            Logs.Add(new LogMessage(e[i].Ex));
            sb.AppendLine(e[i].FileName);
            WriteLogFile(new LogMessage(e[i].FileName, e[i].Ex));

            if (ex.GetType() == e[i].Ex.GetType()) 
                continue;

            ShowLogError(new LogMessage(sb.ToString(), ex));
            sb.Length = 0;
            ex = e[i].Ex;
        }

//Call ShowLogError if only 1 type of Exception in all of e
        if (!string.IsNullOrEmpty(sb.ToString())) 
            ShowLogError(new LogMessage(sb.ToString(), ex));
    }

    public void ShowLogError(ILogMessage log)
    {
        //Extra formatting left out as its irrelevant to code sample
        XtraMessageBox.Show(log.message, log.title);
    }

所以,AddException 试图做的是将ex 中的第一个异常存储在某种标志中,然后迭代其参数并在当前项与标志项不同时向用户发送消息。

测试用例:

  • 添加 3 个文件(fileA.cs、fileB.png、fileC.cs)

预期结果:

  • ShowLogError() 显示 fileA 和 fileC,因为它们引发了相同的错误
  • ShowLogError() 显示 fileB,它抛出硬编码异常,因为它包含“png”

实际结果:

  • ShowLogError() 显示文件 A 和 B,这引发了 2 个不同的异常
  • ShowLogError() 显示 fileC,它与 fileA 抛出相同。

所以我认为我在 AddFiles 方法中使用 GroupBy() 的方式存在问题,但我在这里完全一无所知。哦,另外,我在我的 GroupBy() 声明中收到了 Resharper 的这条注释:Return value of pure method is not used,但我不太确定“纯方法”是什么意思。

编辑:我刚刚尝试使用 OrderBy 而不是 GroupBy,但对于上述测试用例,我得到了相同的结果。

编辑 2:使用我的 OrderBy 而不是 GroupBy,这是我的即时窗口的屏幕截图: ![在此处输入图片描述][1]

添加突出显示只是为了更容易区分三行。

项目 0 和 2 是否应该放在一起,因为它们的 Ex 是同一类型?

编辑 添加 Gert Arnold 答案的屏幕截图以表明它无法编译。我提出了一个确实编译的编辑,它被删除了。当然,我感谢他的帮助,但它并不是 100% 有效。

【问题讨论】:

    标签: c# winforms linq .net-3.5


    【解决方案1】:

    当您拥有 exes 收藏后,基本上您所要做的就是:

    var result = fileExceptions.GroupBy(e => e.Ex.GetType().Name)
        .Select(g => new 
            { 
              g.Key, Files = string.Join("\r\n", g.Select(x => x.FileName).ToArray())
            });
    

    【讨论】:

    • 太棒了,这正是我想要的。我做了一个快速编辑,因为它不是 100% 编译正确,但它非常接近。然后我就能够在结果中循环 foreach r 并使用 r.Key 和 r.Files 调用 ShowLogError。谢谢。
    • @danielhanly 请查看我原帖的编辑。 Gert 的回答虽然很有帮助,但并非 100% 正确。我提交给他的帖子的编辑,你回滚的,有效。
    【解决方案2】:

    我相信您没有捕获“GroupBy”或“OrderBy”子句的结果。

    这个呢:

            List<Type> types = exes.Select(x => x.GetType()).Distinct().ToList();
    

    这为您提供了添加到集合中的独特类型的 FileExceptions

    【讨论】:

    • types 有 1 个项目,即 FileException,因为所有 x 都是 FileExceptions 的集合。使用 x.Ex.GetType 给了我 2 个项目,我的三个文件抛出了两个不同的异常。我想我也许可以处理这个问题。
    • 好吧,我能够修改我的 AddExceptions 方法以利用你建议的这一行,并且我能够通过迭代这个集合和 FileException 集合来实现我想要的结果,并且只要两种异常类型匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多