C# 简化大量重复使用的代码
我有一个物体,有点像C# 简化大量重复使用的代码,c#,C#,我有一个物体,有点像 public class Foo { public string PassChoiseInfo { get; set; } public string FailChoiceInfo { get; set; } public string NAChoiceInfo { get; set; } } 我有一个方法,它返回给我一个对象和适当的数据,如下所示: public Foo GetInfo(TestName testNames) { int t
public class Foo
{
public string PassChoiseInfo { get; set; }
public string FailChoiceInfo { get; set; }
public string NAChoiceInfo { get; set; }
}
我有一个方法,它返回给我一个对象和适当的数据,如下所示:
public Foo GetInfo(TestName testNames)
{
int testNameId = testNames.TestId;
Foo foo = new Foo();
switch (testNameId)
{
case 3:
var passRecord = testNames.TestItems.Where(ex => ex.TestNamesId == 3 && ex.TestItemName == "Pass")
.Select(r => new
{
r.TestItemId,
r.TestItemName,
r.TestItemDirectory
}).FirstOrDefault();
foo.PassChoiseInfo = $"{passRecord.TestItemId},{passRecord.TestItemName},{passRecord.TestItemDirectory}";
var failRecord = testNames.TestItems.Where(ex => ex.TestNamesId == 3 && ex.TestItemName == "Fail")
.Select(r => new
{
r.TestItemId,
r.TestItemName,
r.TestItemDirectory
}).FirstOrDefault();
foo.FailChoiceInfo = $"{failRecord.TestItemId},{failRecord.TestItemName},{failRecord.TestItemDirectory}";
var naRecord = testNames.TestItems.Where(ex => ex.TestNamesId == 3 && ex.TestItemName == "N/A")
.Select(r => new
{
r.TestItemId,
r.TestItemName,
r.TestItemDirectory
}).FirstOrDefault();
foo.NAChoiceInfo = $"{naRecord.TestItemId},{naRecord.TestItemName},{naRecord.TestItemDirectory}";
break;
case 4:
break;
case 5:
break;
case 7:
break;
//6 more cases
}
return foo;
}
}
正如您在我的
GeTInfo
方法中所看到的,我一直在使用相同的代码来更改.where
条件,在很多情况下我都必须这样做。有人能告诉我实现这一目标的最佳方式是什么吗 您可以修复的一位重复代码是传递给Select()
的委托:
目前,您正在创建此委托的三个匿名实例。相反,您可以创建一次委托并将其保存为Func
类型的局部变量,然后将该变量传递给Select()
:
那么就这样称呼它:
var failRecord = GetObject(testNames, ex => ex.TestNamesId == 3 && ex.TestItemName == "Fail");
请给该方法命名一个比GetObject
更合适的名称,但如果不了解更多上下文,我就不能推荐一个好名称:)
现在,如果Where
表达式的形式始终相同,则可以更进一步,将TestNamesId
和TestItemName
应作为参数而不是委托传递给方法:
Foo GetObject(TestName testNames, string id, string name)
{
return testNames.TestItems
.Where(ex => ex.TestNamesId == id && ex.TestItemName == name)
.Select(r => new
{
r.TestItemId,
r.TestItemName,
r.TestItemDirectory
}).FirstOrDefault();
}
您应该创建一个包含重复代码的helper函数
private static dynamic GetDataWithName(TestName testNames, string name)
{
return testNames.TestItems.Where(ex => ex.TestNamesId == testNames.TestId && ex.TestItemName == name)
.Select(r => new
{
r.TestItemId,
r.TestItemName,
r.TestItemDirectory
}).FirstOrDefault();
}
public Foo GetInfo(TestName testNames)
{
int testNameId = testNames.TestId;
Foo foo = new Foo();
switch (testNameId)
{
case 3:
var passRecord = GetDataWithName(testNames, "PASS");
foo.PassChoiseInfo = $"{passRecord.TestItemId},{passRecord.TestItemName},{passRecord.TestItemDirectory}";
var failRecord = GetDataWithName(testNames, "FAIL");
foo.FailChoiceInfo = $"{failRecord.TestItemId},{failRecord.TestItemName},{failRecord.TestItemDirectory}";
var naRecord = GetDataWithName(testNames, "N/A");
foo.NAChoiceInfo = $"{naRecord.TestItemId},{naRecord.TestItemName},{naRecord.TestItemDirectory}";
break;
case 4:
break;
case 5:
break;
case 7:
break;
//6 more cases
}
return foo;
}
}
这是代表式的解决方案。您可以将其重构为纯方法
public Foo GetInfo(TestName testNames)
{
int testNameId = testNames.TestId;
Foo foo = new Foo();
Func<TestItem, dynamic> dynamicBuilder = r => new { r.TestItemId, r.TestItemName, r.TestItemDirectory };
Func<string, int, TestItem> filteringMethod = (name, nameId) => testNames.TestItems.Where(ex => ex.TestNamesId == nameId && ex.TestItemName == name).Select(dynamicBuilder).FirstOrDefault();
Func<TestItem, string> formatMethod = record => $"{record.TestItemId},{record.TestItemName},{record.TestItemDirectory}";
switch (testNameId)
{
case 3:
foo.PassChoiseInfo = formatMethod(filteringMethod("Pass", 3));
foo.FailChoiceInfo = formatMethod(filteringMethod("Fail", 3));
foo.NAChoiceInfo = formatMethod(filteringMethod("N/A", 3));
break;
case 4:
break;
case 5:
break;
case 7:
break;
//6 more cases
}
return foo;
}
publicfoogetinfo(TestName testNames)
{
int testNameId=testNames.TestId;
Foo-Foo=新的Foo();
Func dynamicBuilder=r=>new{r.TestItemId,r.TestItemName,r.TestItemDirectory};
Func filteringMethod=(name,nameId)=>testNames.TestItems.Where(ex=>ex.testnameid==nameId&&ex.TestItemName==name)。选择(dynamicBuilder.FirstOrDefault();
Func formatMethod=record=>$“{record.TestItemId},{record.TestItemName},{record.TestItemDirectory}”;
开关(testNameId)
{
案例3:
foo.PassChoiseInfo=formatMethod(filteringMethod(“Pass”,3));
foo.FailChoiceInfo=formatMethod(filteringMethod(“Fail”,3));
foo.NAChoiceInfo=formatMethod(filteringMethod(“N/A”,3));
打破
案例4:
打破
案例5:
打破
案例7:
打破
//还有6例
}
返回foo;
}
也可以删除
switch
语句,使代码更通用。我将把查询提取到另一个方法,该方法返回您需要的描述字符串
public Foo GetInfo(TestName testNames)
{
string GetItemDescriptionShortcut(string testItemName)
{
return this.GetItemDescription(testNames, testItemName);
}
Foo foo = new Foo
{
PassChoiseInfo = GetItemDescriptionShortcut("Pass"),
FailChoiceInfo = GetItemDescriptionShortcut("Fail"),
NAChoiceInfo = GetItemDescriptionShortcut("N/A")
}
return foo;
}
private string GetItemDescription (TestName testNames, string testItemName)
{
var item = testNames.TestItems
.Where(ex => ex.TestNamesId == testNames.TestId && ex.TestItemName == testItemName)
.Select(r => new
{
r.TestItemId,
r.TestItemName,
r.TestItemDirectory
}).FirstOrDefault();
if (item == null) return null; // or empty string
return $"{item.TestItemId},{item.TestItemName},{item.TestItemDirectory}";
}
你能为
GetInfo
应该做的事情添加一个快速可读的版本吗?对于初学者,你可以使用where子句的字符串参数将查询提取到一个方法中。请你详细说明一下,因为我对代理的了解不是最丰富的,为什么要使用Func
,因为它与3个检查中的2个检查完全相同在哪里
s?我只需要请求TestNamesId
和TestItemName
作为parameters@Code“委托”是指引用方法的变量。在C中,您可以将其称为函数指针。您的r=>…
表达式是一个“lambda表达式”,用于创建一个匿名委托,该委托由Select()
调用。在这里,我将展示如何只创建一次代理,并在多个调用中重用它。谢谢,我将尝试一下,并让您知道我是如何得到代理的on@CamiloTerevinto当然,你可以这样做,我把它编辑成了答案。我试图显示从最小到最大的步骤。GetDataWithName
表示返回YourType
,但它返回一个匿名对象,因此这不需要编译。您需要更正GetDataWithName
方法ex.TestNamesId==3
应该是ex.TestNamesId==testNames.TestId
如何将GetDataWithName
的返回类型从Foo
更改为dynamic
?这需要是静态的吗?@krs没有理由不。
private static dynamic GetDataWithName(TestName testNames, string name)
{
return testNames.TestItems.Where(ex => ex.TestNamesId == testNames.TestId && ex.TestItemName == name)
.Select(r => new
{
r.TestItemId,
r.TestItemName,
r.TestItemDirectory
}).FirstOrDefault();
}
public Foo GetInfo(TestName testNames)
{
int testNameId = testNames.TestId;
Foo foo = new Foo();
switch (testNameId)
{
case 3:
var passRecord = GetDataWithName(testNames, "PASS");
foo.PassChoiseInfo = $"{passRecord.TestItemId},{passRecord.TestItemName},{passRecord.TestItemDirectory}";
var failRecord = GetDataWithName(testNames, "FAIL");
foo.FailChoiceInfo = $"{failRecord.TestItemId},{failRecord.TestItemName},{failRecord.TestItemDirectory}";
var naRecord = GetDataWithName(testNames, "N/A");
foo.NAChoiceInfo = $"{naRecord.TestItemId},{naRecord.TestItemName},{naRecord.TestItemDirectory}";
break;
case 4:
break;
case 5:
break;
case 7:
break;
//6 more cases
}
return foo;
}
}
public Foo GetInfo(TestName testNames)
{
int testNameId = testNames.TestId;
Foo foo = new Foo();
Func<TestItem, dynamic> dynamicBuilder = r => new { r.TestItemId, r.TestItemName, r.TestItemDirectory };
Func<string, int, TestItem> filteringMethod = (name, nameId) => testNames.TestItems.Where(ex => ex.TestNamesId == nameId && ex.TestItemName == name).Select(dynamicBuilder).FirstOrDefault();
Func<TestItem, string> formatMethod = record => $"{record.TestItemId},{record.TestItemName},{record.TestItemDirectory}";
switch (testNameId)
{
case 3:
foo.PassChoiseInfo = formatMethod(filteringMethod("Pass", 3));
foo.FailChoiceInfo = formatMethod(filteringMethod("Fail", 3));
foo.NAChoiceInfo = formatMethod(filteringMethod("N/A", 3));
break;
case 4:
break;
case 5:
break;
case 7:
break;
//6 more cases
}
return foo;
}
public Foo GetInfo(TestName testNames)
{
string GetItemDescriptionShortcut(string testItemName)
{
return this.GetItemDescription(testNames, testItemName);
}
Foo foo = new Foo
{
PassChoiseInfo = GetItemDescriptionShortcut("Pass"),
FailChoiceInfo = GetItemDescriptionShortcut("Fail"),
NAChoiceInfo = GetItemDescriptionShortcut("N/A")
}
return foo;
}
private string GetItemDescription (TestName testNames, string testItemName)
{
var item = testNames.TestItems
.Where(ex => ex.TestNamesId == testNames.TestId && ex.TestItemName == testItemName)
.Select(r => new
{
r.TestItemId,
r.TestItemName,
r.TestItemDirectory
}).FirstOrDefault();
if (item == null) return null; // or empty string
return $"{item.TestItemId},{item.TestItemName},{item.TestItemDirectory}";
}