我还没有看到提到delegate的一个事情是,它使得将方法存储在数据结构中变得容易。例如,在功能需求中,我经常会发现像这样的东西:
通过将状态日期设置为事件日期,更新此费用的所有相关句子记录。如果使用引导转介而被处置,相关的句子就是具有“DV”、“ DCV”或“DVS”的句子类型。如果使用缓刑入境被处置,相关的句子就是具有“DEJ”的句子类型。忽略所有其他费用和句子。
解决此问题的一种方法是为句子构建一个类,为费用构建一个类,并从数据集中填充它们,然后将上面的所有逻辑都放入方法中。另一种方法是构建一个不错的大型嵌套条件语句集。
第三种方式更符合Steve McConnell的观察结果,即调试数据比代码更容易,它是定义包含可用于测试语句行的谓词的查找表:
private static readonly HashSet<string> DiversionTypes =
new HashSet() { "DV", "DCV", "DVS" };
private bool SentenceIsDiversion(DataRow r) { return (DiversionTypes.Contains(r.Field<string>("Type"))); }
private bool SentenceIsDEJ(DataRow r) { return r.Field<string>("Type") == "DEJ"; }
private static readonly Dictionary<string, Func<DataRow, bool>> DispoToPredicateMap =
new Dictionary<string, Func<DataRow, bool>>
{
{ "411211", SentenceIsDiversion },
{ "411212", SentenceIsDiversion },
{ "411213", SentenceIsDEJ },
{ "411214", SentenceIsDEJ },
}
这使得更新逻辑看起来像这样:
string disposition = chargeRow.Field<string>("Disposition");
if (DispoToPredicateMap.ContainsKey(disposition))
{
foreach (DataRow sentenceRow in chargeRow.GetChildRows("FK_Sentence_Charge"))
{
if (DispoToPredicateMap[disposition](sentenceRow))
{
sentenceRow.SetField("StatusDate", eventDate);
}
}
}
在这三种方法中,这种方法首先很难想出来(或者如果您不熟悉该技术,也很难理解)。 但是编写覆盖100%代码的单元测试要容易得多,并且当触发条件发生更改时更新也很容易。