您使用什么策略向用户提供某种方法“失败”的原因
例:
public List<Balance> GetBalanceFinale(Periode periode)
{
if (periode == null || periode.DateStart >= DateTime.Now || isBalanceFinished(periode.PeriodeID))
return null;
//My other code...
}
我想告诉用户哪些步骤出错了。我不想在这样的课程中使用消息框。我无法返回故障的描述,因为我已经返回了一些内容。
你通常做什么?有什么建议?谢谢!
答案 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...
}