调用它的方法有条件返回的方法?

发布于 2024-08-27 18:10:40 字数 694 浏览 4 评论 0原文

好吧,这可能有点黑客,但请耐心等待:) 背景是我厌倦了一些方法,一些 if 语句搞乱了整个方法的缩进,例如:

public SomeClass DoStuff(string inputStr)
{
  SomeClass result =null;
  if (IsOpenFilter(inputStr))
  {
    ....
  }

  return result;
}

所以我在想,不会如果我可以做这样的事情,那就太好了:

public SomeClass DoStuff(string inputStr)
{
  Require(IsOpenFilter(inputStr),null);


  ....

  return result;
}

这种情况可能由某种形式的代码契约涵盖,如果是这样,请纠正我:)

这个想法是,如果该语句的计算结果不为 true,它将返回 null。如果该方法没有返回类型,则它只是: Require(IsOpenFilter(inputStr));

所以我想有两个问题,这可以以某种方式完成吗?我对如何通过调用方法进行有条件返回感到困惑。

另一个问题是,这是个好主意吗?像这样对语言进行猴子补丁有点奇怪,但我更喜欢代码的读取方式。如果可以将其放入方法上方的属性中,我会更干净:[Require(IsOpenFilter(inputStr))]

Ok this might be a bit of hack but bear with me :) The background is that i'm tired of methods that that some if-statement to that messes up indention for the whole method, like:

public SomeClass DoStuff(string inputStr)
{
  SomeClass result =null;
  if (IsOpenFilter(inputStr))
  {
    ....
  }

  return result;
}

So I was thinking , wouldn't it be neat if I could do something like this instead:

public SomeClass DoStuff(string inputStr)
{
  Require(IsOpenFilter(inputStr),null);


  ....

  return result;
}

This case might be covered by code contracts in some form, if so please correct me :)

The idea is that if the statement does not evaluates to true it would return null. If there wasn't a return type for the method it would simply be: Require(IsOpenFilter(inputStr));

So I guess there's two questions, can this be done somehow? I'm stumped on how to do a conditional return from calling a method.

The other question is, is this a good idea? It's a bit weird to monkeypatch the language like this but I'd rather like the way the code reads. I would be even cleaner if it could be put into an attribute above the method: [Require(IsOpenFilter(inputStr))]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

临走之时 2024-09-03 18:10:40

我同意安德斯的观点:反转条件并提前返回。当您需要在该返回点显式地进行大量资源清理时,“单一返回点”曾经很有价值;对于 finally 块、using 语句和垃圾收集,它甚至不再是一个有用的指南,IMO。每当您发现自己只是为了获得单个返回点而做一些事情时,请考虑一下它是否实际上使代码更具可读性。

我几乎总是发现,如果在代码中的某个时刻我知道返回值并且在该方法中没有我想要执行的其他操作,那么最好的办法就是立即返回。在我看来,强迫读者查看方法的其余部分以防万一有另一个操作既不优雅也不有用。

我认为一个方法不能表明它应该导致调用者返回是一件好事 - 这种能力听起来像是可读性的噩梦。话虽如此,我已经考虑了一种新的条件返回语句:

return? expression;

如果表达式不为空,则它将返回它的计算值;您可以将它用于不可为 null 的类型,如下所示:

int Foo()
{
    return? Bar(); // Where Bar() has a return type of int?
    ...
}

基本上,它将是与 null 合并运算符等效的 return 语句。

请注意,这对您的情况没有帮助 - 您想要提前返回 null ...

I agree with Anders: invert the condition and return early. "Single return point" used to be valuable when you needed to explicitly do a bunch of resource clean-up at that return point; with finally blocks, using statements and garbage collection it's not even a useful guideline any more, IMO. Any time you find yourself doing something just to get a single return point, consider whether it's actually making the code more readable.

I almost always find that if at some point in the code I know the return value and there are no other actions I want to take within the method, the best thing is to return immediately. Forcing readers to look through the rest of the method just in case there's another action is neither elegant nor useful, IMO.

I think it's a good thing that a method can't indicate that it should cause the caller to return - that ability sounds like a readability nightmare. Having said that, I have considered a new sort of conditional return statement:

return? expression;

This would return the evaluateed value of expression if it's non-null; you could use it for non-nullable types like this:

int Foo()
{
    return? Bar(); // Where Bar() has a return type of int?
    ...
}

Basically it would be the return statement equivalent of the null-coalescing operator.

This wouldn't help in your case, mind you - you want to return null early...

人事已非 2024-09-03 18:10:40

像这样重写您的第一个示例怎么样:

public SomeClass DoStuff(string inputStr) 
{ 
  if (!IsOpenFilter(inputStr)) 
      return null;

  SomeClass result =null; 

  // Some code .... 

  return result; 
} 

看起来您正在尝试坚持每个函数中一个返回点的旧约定。简而言之:一次返回是具有显式资源处理的语言的遗产。长篇故事可以在一些旧的 SO 帖子中找到:

What about rewriting your first example like this:

public SomeClass DoStuff(string inputStr) 
{ 
  if (!IsOpenFilter(inputStr)) 
      return null;

  SomeClass result =null; 

  // Some code .... 

  return result; 
} 

It looks like you are trying to stick to the old convention of one return point in each function. To make it short: Having one return is a heritage from languages with explicit resource handling. The long story is available in some old SO posts:

┾廆蒐ゝ 2024-09-03 18:10:40

这个解决方案可能非常混乱,我将其发布在这里只是为了好玩作为有趣的选择。

您可以在函数外部使用yield return hack和控制流程。

像这样的事情:

public SomeClass Foo(string input)
{
  return FooInner(input)
    .First(i => !i.continueFlow)
    .value;
}

IEnumerable<(bool continueFlow, SomeClass value)> FooInner(string input)
{
  yield return (IsOpenFilter(), null);
  yield return (OtherCondition(), null);
  
  SomeClass result = null;
  
  // some code
  
  yield return (false, result);
}

这将返回第一个值,其中 continueFlowfalse 并且不继续。一定不要忘记最后一个yield return - First方法可能会抛出异常。

This solution can be quite messy, I post it here just for fun as interesting option.

You can use yield return hack and control flow outside of function.

Something like this:

public SomeClass Foo(string input)
{
  return FooInner(input)
    .First(i => !i.continueFlow)
    .value;
}

IEnumerable<(bool continueFlow, SomeClass value)> FooInner(string input)
{
  yield return (IsOpenFilter(), null);
  yield return (OtherCondition(), null);
  
  SomeClass result = null;
  
  // some code
  
  yield return (false, result);
}

This returns first value where continueFlow is false and do not continue. Be sure to not forget last yield return - First method can throw exception.

橘虞初梦 2024-09-03 18:10:40

所以我想有两个问题,这可以以某种方式完成吗?我对如何通过调用方法进行有条件返回感到困惑。

这里有几个选项,但首先要做的事情是:您需要一个控制流语句,例如 return goto 或 throw 来执行此操作。

因此,我们只剩下这些选项:

  1. 尽早返回 null。这很容易做到,足以满足大多数用例,而且不麻烦。
  2. 使用抛出异常的 Contract.Requires()
  3. 可能使用 OneOf<>来自 nuget,这样您就可以避免异常,但仍指定错误原因
  4. 拆分检查和逻辑:

也许像这样?

public SomeClass? DoStuff(string inputStr)
{
  return ArgumentsValid() ? Logic() : null;
  
  bool ArgumentsValid() => !IsOpenFilter(inputStr);
  
  SomeClass Logic()
  { 
    // Logic here
  }
}

So I guess there's two questions, can this be done somehow? I'm stumped on how to do a conditional return from calling a method.

You have a few options here, but first things first: You need a control flow statement like return goto or throw to do this.

So that leaves us with these Options:

  1. Return null early. This is easy to do, sufficient for most use cases and not hacky.
  2. Use Contract.Requires() that throws an Exception
  3. Maybe use OneOf<> from nuget so you can avoid exceptions but still specify the error reason
  4. Split the checks and the logic:

Maybe like this?

public SomeClass? DoStuff(string inputStr)
{
  return ArgumentsValid() ? Logic() : null;
  
  bool ArgumentsValid() => !IsOpenFilter(inputStr);
  
  SomeClass Logic()
  { 
    // Logic here
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文