如何评价为什么一个方法返回它返回什么
你用什么策略来给用户之所以一定的方法“失败”如何评价为什么一个方法返回它返回什么
例:
public List<Balance> GetBalanceFinale(Periode periode)
{
if (periode == null || periode.DateStart >= DateTime.Now || isBalanceFinished(periode.PeriodeID))
return null;
//My other code...
}
我想告诉用户哪个步骤出错了。我不想在这样的类中使用消息框。我无法返回失败的描述,因为我已经返回了一些东西。
你通常做什么?有什么建议?谢谢!
我假设你不想抛出异常,否则你已经这样做了。就像警告/警告而不停止执行程序。在这种情况下,您仍然可以使用异常,只是不要抛出异常,而是将其作为输出参数传递,或者放在用户可以根据需要访问它的地方。如果这看起来超过了顶部,那么只需使用一条消息。
将它作为'尝试'方法也可能是一个好主意。它清楚地表明该方法在某些条件下容易发生故障。
这些都是不同的选择:
public bool TryGetBalanceFinale(Periode periode, out List<Balance> list, out string msg)
{
// return false if anything is wrong, and have an out parameter for the result & msg
}
public bool TryGetBalanceFinale(Periode periode, out List<Balance> list, out Exception ex)
{
// return false if anything is wrong, and have an out parameter for the exception
}
上述前两个是我的两个首选的方法。以下是可能还有,但它们确实有点不标准:
public Tuple<string, bool> TryGetBalanceFinale(Periode periode, out List<Balance> list)
{
// return false if anything is wrong, and include message in the returned Tuple
}
// an anonymous type approach
public object TryGetBalanceFinale(Periode periode, out List<Balance> list)
{
return new {
Successful = false,
Message = // reason why here
};
}
// a functional approach
public List<Balance> list GetBalanceFinale(Periode periode, Action<String> messageAct)
{
// when something is wrong, do:
messageAct("Something went wrong...");
}
我认为“尝试”战略是很有道理的,当你考虑如何将用于:
string message;
List<Balance> result;
if (!TryGetBalanceFinale(periode, out result, out message))
{
// examine the msg because you know the method failed
Console.WriteLine(message);
}
else
{
// you know the method succeeded, so use the result
Console.WriteLine("The result is: " + result.ToString());
}
您可以使用描述性消息抛出异常。
不例外在这种情况下不必要的性能影响? –
不是一个描述性消息,您可能需要多语言支持。抛出一个自定义异常并设置枚举。你可以在你的图形用户界面上捕捉并解析它。 – DanDan
@GlennFerrieLive,这个问题应该是争论的例外。如果是这样,那么就这样对待它。在类似于问题的情况下,'ArgumentException'是完全合理的。 –
如果我需要返回一个值和一条消息,我只是使用一个out参数。
public List<Balance> GetBalanceFinale(Periode periode, out string errorMessage)
{
if (periode == null)
{
errorMessage = "Periode is null";
return null;
}
// Other checks
}
然后就这样称呼它
string errorMessage;
var value = GetBalanceFinale(periode, out errorMessage);
if(value == null)
// Do whatever with errorMessage
在我看来,它更有意义的是List作为out参数。这是一个标准的做法,就像.NET中的所有'TryParse'方法等一样。 –
你可以分解你的逻辑为3次独立的测试,然后定义一个“出”参数来返回“原因”
public List<Balance> GetBalanceFinale(Periode periode, out string reasonFailed)
{
reasonFailed = false;
if (periode == null)
{
reasonFailed = "preiod is null";
return null;
}
// etc.....
//periode.DateStart >= DateTime.Now || isBalanceFinished(periode.PeriodeID))
//My other code...
}
与布兰登所说的一样,我想。领带去跑步者。 –
如果你认为你的答案与其他人的答案相同,那么删除你的答案(通常是提高另一答案),特别是如果其他答案是首先发布的话。 –
考虑抛出异常而不是返回null。
在这种情况下,您将能够为每个异常提供描述性信息,以后可以正确处理并提供给调用者。
请勿在您的帖子中使用签名或标语。 http://stackoverflow.com/faq#signatures – Greg
我喜欢将我的结果包装在ResultState<T>
对象中(通常用于Json或Xml序列化)。如果您正在为别人构建一个框架供消费者使用,可能会有所帮助,因为每个结果都可以由消费者以相同方式处理。
public class ResultState<T>
{
public T ResultValue { get; set; }
public Exception ExceptionThrown { get; set; }
public bool IsValid { get; set; }
public string FriendlySummary { get; set; }
// whatever else properties you think are needed
}
public interface IResultState<T>
{
public T ResultValue { get; }
public Exception ExceptionThrown { get; }
public bool IsValid { get; }
public string FriendlySummary { get; }
// whatever else properties you think are needed
}
public IResultState<List<Balance>> GetBalanceFinale(Periode periode)
{
ResultState<List<Balance>> result = new ResultState<List<Balance>>();
try
{
if (periode == null
|| periode.DateStart >= DateTime.Now
|| isBalanceFinished(periode.PeriodeID))
{
result.IsValid = false;
result.FriendlySummary = "Periode is in an invalid state.";
}
//My other code...
result.ResultValue = new List<Balance>();
result.ResultValue.Add(...);
}
catch(Exception ex)
{
result.IsValid = false;
result.Exception = ex;
// Ambigious is bad.. so for bad example..
result.FriendlySummary = "An unknown exception happened.";
}
}
你需要重新因子您的代码第一。在致电GetBalanceFinale
之前,您可以验证它并在验证失败时显示正确的消息。如果验证通过,您可以拨打GetBalanceFinale
方法。
有时您可能无法在调用方法之前进行所有验证。在这种情况下,你可以用适当的信息抛出异常或使用参数。
以前替代我的方法是Notification模式。
这是一种从您的域图层获取信息并进入演示文稿的方式。例如,创建如下所示:
public class Notification
{
public List<Message> Messages;
public bool HasMessages;
// etc
}
并将其实例用作您的域的属性。
然后你可以做这样的事情:
myDomain.GetBalanceFinale(periode);
if(myDomain.Notification.HasMessages)
// get the messages and do something with them
尽管我从不特别喜欢'out'参数,但我认为这个解决方案非常简洁! – Mathieu
匿名类型的方法让我感到非常恐怖。我宁愿使用实际类型或“元组”。传递如何处理错误的“行动”的想法有点奇怪,但在某些情况下非常有效。在很多情况下,人们可以比这更进一步,只是将整个事情包装在一个班级中。如果你这样做,你会失败成为一个事件。 – Brian