Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 结果对象而不是输出参数_C#_Asp.net_Generics_Error Handling_Out - Fatal编程技术网

C# 结果对象而不是输出参数

C# 结果对象而不是输出参数,c#,asp.net,generics,error-handling,out,C#,Asp.net,Generics,Error Handling,Out,我的一位同事提出了一个有趣的想法,但我们都有点不确定可能出现的复杂情况 目前,我们的大多数方法都有一个“out”参数来返回消息列表(成功、错误等)。就像这样 public bool Delete(int id, out List<UIMessage> uiMessages) { //Delete stuff bool wasDeleteSuccessful = //set bool here List<UIMessages> uiMessages

我的一位同事提出了一个有趣的想法,但我们都有点不确定可能出现的复杂情况

目前,我们的大多数方法都有一个“out”参数来返回消息列表(成功、错误等)。就像这样

public bool Delete(int id, out List<UIMessage> uiMessages)
{
    //Delete stuff
    bool wasDeleteSuccessful = //set bool here
    List<UIMessages> uiMessages = //Set messages here

    return wasDeleteSuccessful
}
public ResultObject<bool> Delete(int id)
{
    //Delete stuff
    bool wasDeleteSuccessful = //set bool here
    List<UIMessages> uiMessages = //Set messages here

    return new ResultObject<bool>(wasDeleteSuccessful, uiMessages)
}
public bool Delete(int-id,out-List-uiMessages)
{
//删除内容
bool wasDeleteSuccessful=//在此处设置bool
List uiMessages=//在此处设置消息
返回成功
}
我们正在考虑返回一个新对象的想法,该对象将具有T类型属性和列表属性。就像这样

public bool Delete(int id, out List<UIMessage> uiMessages)
{
    //Delete stuff
    bool wasDeleteSuccessful = //set bool here
    List<UIMessages> uiMessages = //Set messages here

    return wasDeleteSuccessful
}
public ResultObject<bool> Delete(int id)
{
    //Delete stuff
    bool wasDeleteSuccessful = //set bool here
    List<UIMessages> uiMessages = //Set messages here

    return new ResultObject<bool>(wasDeleteSuccessful, uiMessages)
}
公共结果对象删除(int-id)
{
//删除内容
bool wasDeleteSuccessful=//在此处设置bool
List uiMessages=//在此处设置消息
返回新的ResultObject(wasDeleteSuccessful,uiMessages)
}

我敢肯定,这里唯一的好处是我们不必处理“out”参数,但我们没有考虑哪些缺点?

没有主要缺点,只是新的结果对象不必要的额外复杂性,它包含与先前使用
out
参数实现完全相同的信息。如果这些方法被大量执行,那么(性能和内存方面)您可能会更好地使用更少的对象进行实例化,从而使用第一个(out)实现


我个人更喜欢给定示例中的out实现,因为您的方法倾向于遵循。Try parse模式通过返回bool来通知您成功,并为您提供result/info对象in-out参数。在这种情况下,您的命名有点错误。与其删除,不如将方法命名为TryDelete

通常最好返回值,而不是变异变量。通过返回值而不是变异变量,您可以在不能变异变量的上下文中使用方法。例如,删除是异步的主要候选,因为它可能是一个高延迟操作。改变调用方变量的方法很难实现异步

然而,这将是一个很好的时间退一步,问问你是否真的在做正确的事情摆在首位。这种方法的合同似乎很奇怪。我希望删除某些内容的方法返回void,因为删除是一种效果,而不是值的产生。我希望在发生故障时,故障状态将存储在抛出的异常中,而不是消息列表中

查看为该问题提供解决方案的NuGet包(需要.NET标准2)

它的核心是
IDomainResult
(类似于您的
ResultObject
),具有以下属性:

IReadOnlyCollection Errors{get;}//错误消息的集合(如果有)
bool issucess{get;}//标志,当前状态是否成功
DomainOperationStatus状态{get;}//域操作的当前状态:成功、错误、未找到
从这里开始,在方法中有两个返回对象的选项:

  • 一个泛型
    IDomainResult
    ,它通过添加
    T值{get;}
    属性来扩展上述结果
  • 从方法返回,如
    (T,IDomainResult)
  • 这一切都是通过50+扩展方法进行的,例如

    //使用int的成功结果
    (值,状态)=IDomainResult.Success(10);//数值=10;状态。状态为“成功”
    //相同,但包装在一个任务中
    var res=IDomainResult.SuccessTask(10);//res是任务
    //错误消息
    IDomainResult=IDomainResult.Error(“啊!”);//res.状态为'Error',res.Errors=new[]{“Ahh!”}
    //应为int时出错
    (值,状态)=IDomainResult.Error(“啊!”);//value=0,state.Status为'Error'和state.Errors=new[]{“Ahh!”}
    
    例如:

    公共异步任务GetInvoice(int invoiceId) { 如果(发票ID<0) //返回验证错误 返回IDomainResult.Error(“更加努力”); var invoice=wait DataContext.Invoices.FindAsync(invoiceId); 如果(发票==null) //返回未找到的响应 返回IDomainResult.NotFound(); //返回发票 IDomainResult.Success(发票); } 或者,如果您反对,则使用更传统的方法签名:

    公共异步任务GetInvoice(int invoiceId) { 如果(发票ID<0) //返回验证错误 返回DomainResult.Error(“更加努力”); ... } 它还有20多个扩展,用于将基于
    IDomainResult
    的类型转换为相应的
    IActionResult
    ,以便从WebAPI控制器方法返回


    请在查看样品。这都是你的主意。

    这个主意并不新鲜。检查实现和用例。考虑到
    List
    是一种引用类型,调用方可以安全地传入一个初始化的实例,然后该方法将添加到该实例中。只是另一种选择。@PoweredByOrange哦,对了。。。这是有道理的,人们可以使用
    out
    参数,有些则不行。我想说,这只是一种更干净的方式来做你已经在做的事情。我不会把这主要是基于意见的,因为它会问潜在的问题,但请记住,你的问题有点抽象。@ USE2020116我会说是一个更合适的姐妹网站,关于软件设计实践的问题。我不认为奇怪的是,删除方法返回BoOL;这种方法在集合中很常见(例如,因为用户只关心集合排除了对象,而不关心对象是否被删除。这种方法在并发集合中也很常见。@EricLippert如果删除失败是常见的(不是例外)在这种情况下,您是否仍然建议使用异常或可能返回带有失败原因的对象?我这样说是因为我越来越多地看到人们使用EXE的“趋势”