【发布时间】:2012-03-05 04:56:50
【问题描述】:
请忽略这样的模式是否真的是个好主意。基本原理是我想捕获抛出的错误,或者插入/更新/删除的记录数不匹配。我不想重复这个逻辑,当时这种定制感觉就像它只适用于不超过四个长的“脚本”方法。
我的第一步是使用匿名函数。
public void DoSqlAction(Func<bool> f, string task, string ctx, ref bool cont, List<ResultInfo> resultInfo) {
if (cont) {
bool ret = false;
try {
if (f.Invoke()) {
resultInfo.Add(new ResultInfo(seq, task, "Success", ctx, true));
cont = true;
} else {
resultInfo.Add(new ResultInfo(seq, task, "Fail", ctx, false));
cont = false;
}
} catch (Exception ex) {
resultInfo.Add(new ResultInfo(seq, task, "Error: " + ex.Message, ctx, false));
cont = false;
}
}
}
如果我尝试使用它:
DoSqlAction(() => 1 == cx.Execute(someSql, anonymousTypeWithClassInstanceInside), "add item", refinfo.ToString(),ref cont, resultInfo);
anonymousTypeWithClassInstanceInside
出现错误:
不能在匿名方法、lambda 表达式或查询表达式中使用 ref 或 out 参数“abc”
解决方案是摆脱委托Func<bool> f。我正在写这篇文章(也许它应该是一篇博客文章?),因为它觉得生成的编译时错误有点障碍。
在这篇文章中,我发现了 Eric 文章的链接:
C# Cannot use ref or out parameter inside an anonymous method body
这里
在看到 foreach 是如何实现的之后,我开始思考......嗯......也许我正在寻找可定制的语法糖。
现在在 C#4 中可以实现吗?在 C#5 中有可能吗?这让我考虑在未来的某个时候研究http://nemerle.org,但我真的很想留在 C# 中。
【问题讨论】:
-
考虑 +1 仅仅是因为“......感觉生成的编译时错误 [that] 有点障碍。”我不明白为什么你不能在这里只返回 true 或 false 并确定将
SqlActions 列表作为输入的调用方法中的延续 - 是否有其他代码实际使用 cont? -
为什么你不直接写它来返回 true 或 false 来表示成功或失败,而不是使用 ref 参数?或者返回一个 ResultInfo。我错过了什么吗?
-
@arootbeer:同意。这就是我所说的“撕掉 Func f”的意思。这只是在这种情况下代码演变的方式+在实现重用模式之后,我必须去更改所有内容。 “布尔”的想法不如 lamda 灵活......如果我们最终发现有一个我们想要实现的横切模式怎么办?发现这一点后,我倾向于总是使用某种 OO 模式,而不是基于语言的想法。
-
... 和 lamdas 是强大的小设备。我不喜欢这样的东西绊倒。也许它与 lamda 领域有关。
-
我不会评论你写的代码是否好。但它应该编译得很好。而且由于您在 lambda 表达式中没有任何
ref或out,我认为您的问题不在您发布的代码中。