正在使用"淘汰"的不良做法

Ant*_*ott 8 c# lambda anti-patterns moq

我刚刚为我编写的方法添加了一个out bool参数,以便在我的UI中收到警告.我已经使用了out而不是让方法本身返回false/true,因为这意味着DoSomething失败/成功.我的想法是warnUser会指出警告实际上是什么,而不必查看方法的实现.

原始代码

public void DoSomething(int id, string input);
Run Code Online (Sandbox Code Playgroud)

新规范

public void DoSomething(int id, string input, out bool warnUser);
Run Code Online (Sandbox Code Playgroud)

我正在使用Moq来测试此代码,但它不支持out/ref参数,因为Lambda表达式不支持它们

测试代码

mockService.Verify(It.IsAny<int>(), It.IsAny<string>(), It.IsAny<bool>());
Run Code Online (Sandbox Code Playgroud)

因此,采用参数不好的做法,如果是的话我该怎么办呢?

Jon*_*eet 9

在void方法中使用out参数通常是个坏主意.你说你已经使用它"而不是让方法本身返回false/true,因为这意味着DoSomething失败/成功" - 我不相信这意味着什么.通常在.NET中,故障通过异常而不是真/假来指示.

out 参数通常比返回值更难使用 - 特别是,你必须有一个正确类型的变量来处理,所以你不能只写:

if (DoSomething(...))
{
   // Warn user here
}
Run Code Online (Sandbox Code Playgroud)

您可能需要考虑的另一种方法是枚举,指示所需的警告级别.例如:

public enum WarningLevel
{
    NoWarningRequired,
    WarnUser
}
Run Code Online (Sandbox Code Playgroud)

然后该方法可以返回a WarningLevel而不是bool.这会让你更清楚你的意思 - 尽管你可能想稍微重命名一下.(虽然我完全明白为什么你在这里使用它,但很难用诸如"DoSomething"之类的metasyntactic名称给出建议.)

当然,另一种选择是您可能希望存在更多信息 - 例如警告的原因.这可以通过枚举完成,或者您可能想要完全提供更丰富的结果.


Mar*_*ell 7

out非常有用的构造,特别是在模式,比如bool TryGetFoo(..., out value),你想知道"如果"和"什么"分开(和可空不一定是一个选项).

但是 - 在这种情况下,为什么不做到:

public bool DoSomething(int id, string input);
Run Code Online (Sandbox Code Playgroud)

并使用返回值来发出信号?

  • @Antony - 然后考虑重命名方法,使**有意义; 或者,坦率地说,克服它; p返回值并不意味着"失败"(这不是C/C++) - 它意味着"这里是返回值".它是一个"bool"的事实是无关紧要的. (3认同)
  • @Marc Gravell我认为在.NET 4中,使用Tuple <bool,MyThing>可能会更清楚,因为输入(方法参数)与输出(返回值)分开,仍然提供"if"和"what" .当然,元组在lambdas中工作得很好. (2认同)
  • @Antony - 我不确定我是否看到了这个评论的重要性; 然而,你*做*似乎只返回了一个值 - 当你可以使用`return`时,为什么要使用`out`? (2认同)