【问题标题】:dotnet return 1 of 2 types [duplicate]dotnet 返回 2 种类型中的 1 种 [重复]
【发布时间】:2018-11-25 07:59:19
【问题描述】:

我有一个简单的方法设置来创建条目,如果成功,则返回创建的条目。如果没有返回 ValidationError。

public async Task<MyNewEntry> CreateEntry(MyUser user, MyEntryRequest entry)

如果条目有效,这将非常有用。但是,如果验证失败,我想返回 ValidationError。

我试过这样做:

public async Task<MyNewEntry | ValidationError> CreateEntry(MyUser user, MyEntryRequest entry)

但是它没有编译。如何构造此方法,使其能够返回 MyNewEntryValidationError

【问题讨论】:

  • AFAIK 没有内置任何东西。您可以将它们包装在 Either 结构中(如 Scala has),或者例如将验证错误包装在一个异常中,或者将一个作为输出参数返回,另一个返回 null(如果设置),但我不确定这些是否超级干净。
  • 返回两种不同的类型通常是个坏主意。您可以简单地在 MyNewEntry 类中设置一个“有效”标志来指示成功或失败。
  • 是的,我试图避免修改类型,因为它们是第三方。我想我会做一个知道如何处理它的包装类。
  • 使用Tuple?家长班?真的听起来你应该抛出一个异常。验证失败不是您可以在编译时解决的问题
  • 这将是异常驱动的设计,考虑到异常对应用程序的影响,在任何情况下都应该避免这种情况。当你知道会发生什么时,避免抛出异常。 Validation-Result,不管是哪一种,都不例外。

标签: c# .net


【解决方案1】:

为此,您可以使用 Result-Type,它由一个属性“bool Success”和一个 Error 以及一个 Entry 属性组成,该属性始终只有一个填充一个值,具体取决于您的成功方法。

public class CreateEntryResult
{
    public bool Success {get;set;}
    public MyNewEntry Entry {get;set;}
    public ValdidationError Error {get;set;}
}

为了节省一些内存(你会在每个结果上创建一个额外的对象),你也可以返回一个结构。只需将我的代码中的“class”关键字替换为“struct”即可。然后包含的引用将作为值传递,您不必考虑对垃圾收集的任何影响。

另一种我近年来很少看到的方法是“尝试”模式,您可以在其中返回结果类型(通常是布尔值)并使用输出参数来返回您的值。 我不确定 out-parameters 如何与 async 一起工作。

bool TryCreateEntry(..., out MyNewEntry entry, out ValidationError error)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 2016-09-09
    • 1970-01-01
    相关资源
    最近更新 更多