gpt4 book ai didi

c# - 从 C# 中的方法返回值或错误消息的最佳做法是什么?

转载 作者:行者123 更新时间:2023-11-30 19:57:31 27 4
gpt4 key购买 nike

我正在尝试为从 c# 中的函数/方法返回值或错误消息找到最干净的解决方案。

目前我已经尝试过:

public float ValidateValue (float value)
{
if (value == VALID_VALUE)
{
return value;
}
else
{
throw new ArgumentException("Invalid value", "value");
}
}

这个解决方案似乎足够好,但在 Clean Code Cheap Sheet 中我发现:

Using Exceptions for Control Flow – Don't do this

Using exceptions for control flow: has bad performance, is hard to understand and results in very hard handling of real exceptional cases.

最佳答案

如果输入无效,你会怎么做?

如果您在 UI 级别编写代码以获取用户的输入,那么最有意义的做法是:

private bool IsValid(float value)
{
return value == VALID_VALUE; // replace with real check.
}

然后在调用代码中您将拥有:

public void ReactToInput()
{
float value = HoweverYouGetTheFloatFromTheUser();
if(!IsValid)
{
//Code to display error message.
}
else
{
//Code to do something useful.
//
//Code to display result.
}
}

因为你在这个级别的工作是“接受用户给我的东西,尽我所能返回他们想要的东西”,在这个级别最好让用户做一些不正确的事情。

如果您正在为其他代码编写代码以供使用,那么最有意义的做法是:

private void CheckValid(float valid)
{
if(value != VALID_VALUE) // replace with real check.
throw new ArgumentException();
}

然后在调用代码中您将拥有:

public float DoWork(float value)
{
CheckValid(value)
//Code to do something useful.
//
//Code to return result.
}

在这里,您的工作是干净利落地完成方法的任务,并返回有意义的结果(如果没有结果,则返回 void)。如果你不能做那项工作,因为你得到的输入是无意义的(或出于任何其他原因),那么你需要尽快停下来处理这个问题。您可以通过每次都返回一个错误/成功代码并让调用代码每次都检查它来做到这一点,但是虽然这种方法确实有一些优势,但异常让我们:

  1. 着重于正确的行为。
  2. 放弃异常(exception)。

以1为例,比较:

private bool WithExceptions()
{
return A() > B() && C() > D();
}

private bool WithExplicitChecks(out bool result)
{
result = false;
int a;
int b;
if(!A(out a))
return false;
if(!B(out b))
return false;
if(a <= b)
return true;
int c;
int d;
if(!C(out c))
return false;
if(!D(out d))
return false;
result = c > d;
return true;
}

以 2 为例,考虑:

private void A()
{
if(_someField == null)
throw new InvalidOperationException("field not ready");
_someField.DoSomething();
}
private void B()
{
A();
}
private void C()
{
B();
}
private string D()
{
try
{
C();
}
catch(InvalidOperationException)
{
Console.Error.WriteLine("Was not ready");
}
}

很明显,一个真实的案例会让 B()C() 做更多,但我们可以在这里看到只有 A()必须担心引发异常,只有 D() 处理它们,B()C() 都可以专注于主要问题。*

这两种方法可以混合使用。考虑:

private static string CheckValid(string path)
{
if(path.Length == 0)
return "You cannot enter an empty file path";
switch(path[path.Length - 1])
{
case '\\':
case '/':
return "You cannot enter a directory path";
}
return null;
}
public static void Main(string[] args)
{
Console.WriteLine("Enter a file path");
var path = Console.ReadLine().Trim();
var validationError = CheckValid(path);
if(validationError != null)
Console.Error.WriteLine(validationError);
else
{
try
{
using(var reader = new StreamReader(path))
Console.WriteLine(reader.ReadToEnd());
}
catch(FileNotFoundException)
{
Console.Error.WriteLine("File not found");
}
catch(UnauthorizedAccessException)
{
Console.Error.WriteLine("Access denied");
}
catch(IOException ioe)
{
Console.Error.WriteLine(string.Format("I/O Exception: {0}", ioe.Message));
}
}
Console.Read();
}

这个简单的程序从用户那里获取文件路径,打开相关文件并将内容输出为文本。它采用两种错误处理方法。

因为我们可以很容易地检查是否为空的无效输入,或者以 /\ 结尾的输入,这是通过简单的控制流完成的,我们会报错消息而不是做某事。

其他问题我们只能通过尝试打开文件失败来了解,因此在这些情况下我们会处理异常。我将对两类问题的显式检查与对一类问题的显式检查结合起来,并采取相应的行动。

这里还有第三种异常处理;如果发生我根本没有预料到的异常,程序将失败并转储异常消息以用于调试目的。在您没有捕获所有异常但非常有用的异常的任何地方都是这种情况;因为我没有一揽子 catchcatch(Exception) 我不会混淆我期望处理的异常(去我处理它们!)存在异常是因为我犯了一个错误,没有意识到它们可能会发生(糟糕!现在我必须修复它)。

这是一个简单的程序,它从用户那里获取文件路径,并输出文件的内容。请注意,它结合了两种方法:

*尽管如此,请始终考虑如果异常突然发生,方法中启动的某些内容可能无法完成。

关于c# - 从 C# 中的方法返回值或错误消息的最佳做法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29768502/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com