如何"剪切和粘贴" foreach循环到一个方法

时间:2017-09-06 15:53:53

标签: c#

我有以下方法。 我的问题主要是关于"剪切和粘贴"将foreach循环转换为方法(如何)。 foreach循环决定了两件事。首先,它负责向errorMessages列表添加消息,其次负责将test项添加到executedTests列表。我问这个问题,因为这是一个问题"我经常穿着它。

我想保持我的ConvertItem方法清洁,所以我想&#34;剪切并粘贴&#34; foreach循环到(私有)方法。这很容易做到。但是,一个方法只能返回1个对象。(我知道有一些特殊的解决方案,例如我自己使用:ConvertItem returing Result<KeuringRegel, Keuring>)。但编程语言被设计为返回void,null或仅返回1个对象。

1解决方案是使errorMessages成为一个类属性,这样我就可以从类中的每个方法调用它。但是,到目前为止,并非所有方法都会使用此errorMessages属性,因此它并不合理。

private Result<KeuringRegel, Keuring> ConvertItem(KeuringRegel row, int rownr)
{
    List<string> errorMessages = new List<string>();

    //Check A
    Debiteur debiteur = _Tools_NawContext.Debiteur.SingleOrDefault(item => item.Naam.Equals(row.Projekt, StringComparison.OrdinalIgnoreCase));
    if (debiteur == null) { errorMessages.Add("Regel " + rownr + ": Debiteur.naam '" + row.Projekt + "'(row.Projekt) bestaat niet in db."); }
    //Check B, C, D and more left for brevity. Also other code, which i.e. use "row" and "rownr" left for brevity

    List<string> testNames = row.testNames.Keys.ToList();
    if (testNames.Any() == false) { errorMessages.Add("Regel " + rownr + ": bevat geen enkele test."); }

    Keuring keuring = new Keuring();//Constructor properties and code in which this "keuring" object is used left out for brevity

    List<Test> executedTests = new List<Test>();
    foreach (string testNaam in testNames)
    {
        Test test = _Tools_NawContext.Test.Include(item => item.Test2Testmethode).SingleOrDefault(item => item.Naam.Equals(testNaam, StringComparison.OrdinalIgnoreCase));
        if (test == null) {
            string testValue = row.testNames[testNaam].ToString();
            if (string.IsNullOrWhiteSpace(testValue) == false) {
                errorMessages.Add("Regel " + rownr + ": test.naam '" + testNaam + "' met waarde '" + testValue + "' bestaat niet in db.");
            }
        } else {
            executedTests.Add(test);
        }
    }

    Result<KeuringRegel, Keuring> convertResult;
    if (errorMessages.Any()) convertResult = new Result<KeuringRegel, Keuring>(row, keuring, errorMessages);
    else convertResult = new Result<KeuringRegel, Keuring>(row, keuring);
    return convertResult;
}

建议的做事方式是什么?也许那里有一些好文章?

1 个答案:

答案 0 :(得分:0)

如果你只是想移动&#39; foreach循环中的代码循环到一个方法,这似乎是你的直接问题,你可以做这样的事情。请注意,我无法编译您的代码,因此可能会出现小的拼写错误和/或语法错误,但这应该会让您有所了解。

foreach (string testNaam in testNames)
{
    CantThinkOfAGoodName(testNaam, row, rownr, ref errorMessages, ref executedTests);
}

public static void CantThinkOfAGoodName(string testNaam, KeuringRegel row, int rownr, ref List<string> errorMessages, ref List<Test> executedTests)
{
    Test test = _Tools_NawContext.Test.Include(item => item.Test2Testmethode).SingleOrDefault(item => item.Naam.Equals(testNaam, StringComparison.OrdinalIgnoreCase));
    AddErrorMessages(test, testNaam, row, rownr, ref errorMessages);
    AddExecutedTests(test, ref executedTests);
}

public static void AddErrorMessages(Test test, string testNaam, KeuringRegel row, int rownr, ref List<string> errorMessages)
{
    if (test == null)
    {
        string testValue = row.testNames[testNaam].ToString();
        if (string.IsNullOrWhiteSpace(testValue) == false)
        {
            errorMessages.Add("Regel " + rownr + ": test.naam '" + testNaam + "' met waarde '" + testValue + "' bestaat niet in db.");
        }
    }
}

public static void AddExecutedTests(Test test, ref List<Test> executedTests)
{
    if (test != null)
        executedTests.Add(test);
}

但那只是转移问题。在我看来,这里更大的问题是你只是试图用一种方法做太多。让我们采取您的原始功能并进行分析。对我而言,这就是它的样子。

private Result<KeuringRegel, Keuring> ConvertItem(KeuringRegel row, int rownr)
{
    // 1. Do a bunch of stuff using `debiteur`.
    //        1.1 Might add to `errorMessages`

    // 2. Get testNames

    // 3. Iterate through testNames and add to `executedTests` and/or `errorMessages`

    // 4. Based on `errorMessages` your `convertResult` is constructed and returned.
}
  • 如果你看一下你的逻辑,1.除了添加errorMessages之外与其他事情无关。
  • 操作2.3.密切相关。
  • 4.中,未使用executedTests
  • 4. errorMessages只与ref的其他内容真正相关。

所以我的建议是将这个功能分解成更小的功能,每个功能都集中在一件事上。我不知道使用out1.时遇到了什么问题,但必要时会使用这些问题,使用它们并没有错。

所以,

  • 在一个功能中移动errorMessages。将ref作为2.传递给它。
  • 3.errorMessages合并为一个函数,然后再次将ref作为executedTests传递。您的代码示例中的使用了4.,因此我认为它没有显示在那里。
  • errorMessages移到另一个方法中,最后传递给{{1}}。您可以考虑编写一个小类/结构来保存返回结果类型。

这只是一种做事方式,但绝对是,在一种方法中做太多是糟糕的设计。这使得维护,调试和测试变得困难。此外,改变线路将是一场噩梦。