如何评价为什么一个方法返回它返回什么

如何评价为什么一个方法返回它返回什么

问题描述:

你用什么策略来给用户之所以一定的方法“失败”如何评价为什么一个方法返回它返回什么

例:

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()); 
} 
+0

尽管我从不特别喜欢'out'参数,但我认为这个解决方案非常简洁! – Mathieu

+0

匿名类型的方法让我感到非常恐怖。我宁愿使用实际类型或“元组”。传递如何处理错误的“行动”的想法有点奇怪,但在某些情况下非常有效。在很多情况下,人们可以比这更进一步,只是将整个事情包装在一个班级中。如果你这样做,你会失败成为一个事件。 – Brian

您可以使用描述性消息抛出异常。

+2

不例外在这种情况下不必要的性能影响? –

+1

不是一个描述性消息,您可能需要多语言支持。抛出一个自定义异常并设置枚举。你可以在你的图形用户界面上捕捉并解析它。 – DanDan

+1

@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 
+1

在我看来,它更有意义的是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... 
} 
+0

与布兰登所说的一样,我想。领带去跑步者。 –

+2

如果你认为你的答案与其他人的答案相同,那么删除你的答案(通常是提高另一答案),特别是如果其他答案是首先发布的话。 –

考虑抛出异常而不是返回null。

在这种情况下,您将能够为每个异常提供描述性信息,以后可以正确处理并提供给调用者。

+3

请勿在您的帖子中使用签名或标语。 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