我有以下方法。 我的问题主要是关于"剪切和粘贴"将foreach循环转换为方法(如何)。 foreach循环决定了两件事。首先,它负责向errorMessages
列表添加消息,其次负责将test
项添加到executedTests
列表。我问这个问题,因为这是一个问题"我经常穿着它。
我想保持我的ConvertItem
方法清洁,所以我想"剪切并粘贴" 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;
}
建议的做事方式是什么?也许那里有一些好文章?
答案 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
的其他内容真正相关。所以我的建议是将这个功能分解成更小的功能,每个功能都集中在一件事上。我不知道使用out
和1.
时遇到了什么问题,但必要时会使用这些问题,使用它们并没有错。
所以,
errorMessages
。将ref
作为2.
传递给它。3.
和errorMessages
合并为一个函数,然后再次将ref
作为executedTests
传递。您的代码示例中的不使用了4.
,因此我认为它没有显示在那里。errorMessages
移到另一个方法中,最后传递给{{1}}。您可以考虑编写一个小类/结构来保存返回结果类型。这只是一种做事方式,但绝对是,在一种方法中做太多是糟糕的设计。这使得维护,调试和测试变得困难。此外,改变线路将是一场噩梦。