我经常使用该模式
bool TryGetX(out X x)
Run Code Online (Sandbox Code Playgroud)
当我需要从可能失败的服务获取数据时。当客户端和服务在尝试检索数据之前都不知道数据是否可用时,我会使用此方法。我从来没有完全满意以这种方式使用out参数,而且我从其他 SO 问题中看到它被认为是一个糟糕的模式。
然而,我还没有看到一个令人信服的替代 API 可以向客户端提示他们的方法调用实际上可能不会返回数据。
我考虑过的替代方案:
X GetX(),如果服务无法提供请求的数据,则GetX()返回null 。我不喜欢这样做,因为很多人不清楚他们是否需要检查是否返回null 。考虑到我在处理过的遗留代码中遇到的空引用异常的数量,人们经常忽略空检查,并且用户会看到一个丑陋的异常框。至少TryGetX方法让客户端清楚数据可能不会返回。即使他们确实检查 null,是否到处都要求if (x == null)真的比TryGetX(out X x)更好?
Try/Catch,如果无法返回数据,GetX()会抛出异常。同样,客户可能没有意识到GetX()会引发异常,即使他们意识到了,你也可以在代码中散布 Try/Catches。
GetXResult GetX(),其中GetXResult类有两个属性:bool Success和X x。这可能是我的首选选择,但随后我有很多结果类,使我的项目变得混乱。
对于返回数据但可能无法返回请求的数据的方法,最好的方法是什么?
最佳方法取决于问题,我怀疑是否存在适合所有问题的“最佳”方法。
X GetX(),如果服务无法提供请求的数据,则 GetX() 返回 null。
如果服务需要返回的所有类型都是可为空的,并且所有这些类型的方法都可以保持某种一致性,那么这根本不是一个坏方法。为了向客户端澄清“null”返回,您可以在方法名称中包含“Try”(文档也对客户端有帮助)。
Try/Catch,如果无法返回数据,GetX() 会抛出异常。
抛出或不抛出异常是服务架构中应该做出的决定。如果您选择在该级别为所有需要的方法抛出异常,则此方法也可以正常工作。(使用文档通知客户)。
GetXResult GetX(),其中 GetXResult 类有两个属性:bool Success 和 X x。
为了解决“类太多”问题,只需使用泛型:
sealed class Result<T> {
private bool success = false;
private T value;
private Result() {
}
public Result(T value) {
this.success = true;
this.value = value;
}
public static Result<T> Failure() {
return new Result<T>();
}
public bool Success {
get {
return this.success;
}
}
public T Value {
get {
if (!this.success) {
throw new InvalidOperationException();
}
return this.value;
}
}
}
Run Code Online (Sandbox Code Playgroud)