如何评估方法返回返回的内容的原因

时间:2011-11-02 17:01:52

标签: c#

您使用什么策略向用户提供某种方法“失败”的原因

例:

public List<Balance> GetBalanceFinale(Periode periode)
    {
        if (periode == null || periode.DateStart >= DateTime.Now || isBalanceFinished(periode.PeriodeID))
            return null;

        //My other code...
     }

我想告诉用户哪些步骤出错了。我不想在这样的课程中使用消息框。我无法返回故障的描述,因为我已经返回了一些内容。

你通常做什么?有什么建议?谢谢!

8 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:5)

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

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

答案 2 :(得分:2)

我喜欢将结果包装在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.";    
  }
}

答案 3 :(得分:2)

我假设你不想抛出异常,否则你就已经做过了。类似于警报/警告而不停止执行程序。在这种情况下,您仍然可以使用异常,只是不要抛出异常,而是将其作为out参数传递,或者将其放在用户可以根据需要访问它的位置。如果这似乎超过顶部,那么只需使用消息。

同时将其定义为“尝试”方法可能是一个好主意。很明显,该方法在某些条件下容易出现故障。

这些都是不同的选择:

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

答案 4 :(得分:2)

您需要先重新分解您的代码。在调用GetBalanceFinale之前,您可以验证它并在验证失败时显示正确的消息。如果验证通过,您可以调用GetBalanceFinale方法。

有时您可能无法在调用方法之前执行所有验证。在这种情况下,您可以使用正确的消息抛出异常或使用参数。

答案 5 :(得分:2)

过去对我有用的替代方案是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

答案 6 :(得分:1)

如果我需要返回值和消息,我只需使用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

答案 7 :(得分:1)

你可以将你的逻辑分解为3个独立的测试,然后定义一个'out'参数来返回“reason”

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...
 }