C# 我应该在重载方法上使用不同的返回类型吗?

C# 我应该在重载方法上使用不同的返回类型吗?,c#,.net,C#,.net,对于重载方法返回不同的返回类型,有什么最佳实践吗?例如,如果我的DAL中有一个Load方法,我要么想加载单个项,要么想加载一组项。我知道我可以使用多种方法: 加载一个对象 MyBusinessObject LoadOne(int id) { } 加载多个对象 MyBusinessObject[] LoadMany(params int[] ids) { } 现在我知道我可以做的是重载一个方法,并有不同的返回类型。像这样: MyBusinessObject Load(int id) { }

对于重载方法返回不同的返回类型,有什么最佳实践吗?例如,如果我的DAL中有一个Load方法,我要么想加载单个项,要么想加载一组项。我知道我可以使用多种方法:

加载一个对象

MyBusinessObject LoadOne(int id)
{
}
加载多个对象

MyBusinessObject[] LoadMany(params int[] ids)
{
}
现在我知道我可以做的是重载一个方法,并有不同的返回类型。像这样:

MyBusinessObject Load(int id)
{
}

虽然似乎没有什么可以阻止我这么做,而且从API的角度来看,它可以保持事情的整洁,但这似乎是个好主意吗?我昨晚遇到了它,我的一部分人认为我不应该这样做,因为我希望为重载方法匹配返回类型

我还可以让Load(intid)方法返回一个只包含一个项的集合。在我看来,这违反了最小惊喜原则,尽管如果您希望返回一个项目,那么您应该返回该项目,而不应该返回包含单个项目的列表

因此,以下是我围绕这些观点的相互矛盾的想法:

  • 重载的方法都应该返回相同的类型
  • 如果方法做相同的事情,不要给它们一堆不同的名称,重载相同的方法名称。从API用户的角度来看,它使事情变得更简单,他们不必遍历一堆不同的方法,这些方法本质上都做相同的事情,但参数不同
  • 返回方法的最明显类型,即如果用户可能需要一组项,则返回一组项;如果用户可能需要一个项,则返回一个项
因此,后两种想法有点超过了第一种,但同时,第一种想法似乎是某种编程的最佳实践


围绕这一实践有什么最佳实践吗?我很想听听其他人对这个问题的看法。

我个人的想法是,从API用户的角度来看,后一种方法似乎更容易理解。

您可以查看现有的API。以LINQ为例,它有返回多个实体的“Select”方法和只返回一个实体的“Single”方法。大多数现有API都有两种不同的方法,而不是重载的方法,我认为这是合乎逻辑的,更具可读性。

我可能会尝试将API显式化,并在名称中使用复数:

Customer LoadCustomer(int id) {...}
Customer[] LoadCustomers(params int[] id) {...}

实际上,
参数在这里很少有用-您通常在编译时不知道ID。

我倾向于遵循您的“关于这个想法的想法”列表中的第一点,即“重载应该返回相同的类型”

但是您可以使用一些不同的场景重载“LoadMany”

public Customer Load(int id)
{
    // return just one customer
}

public List<Customer> LoadMany()
{
    // return every single customer
}

public List<Customer> LoadMany(int statusFilter)
{
    // return a filtered list of customers
}

public List<Customer> LoadMany(DateTime InitialContactFrom)
{
    // return a filtered list of customers
}

public List<Customer> LoadMany(DateTime InitialContactFrom, DateTime InitialContactBefore)
{
    // return a filtered list of customers
}
公共客户负载(int-id)
{
//只返回一个客户
}
公共列表LoadMany()
{
//退回每一位客户
}
公共列表LoadMany(int statusFilter)
{
//返回经过筛选的客户列表
}
公共列表LoadMany(DateTime InitialContactFrom)
{
//返回经过筛选的客户列表
}
公共列表LoadMany(DateTime InitialContactFrom、DateTime InitialContactBefore)
{
//返回经过筛选的客户列表
}

…显然可以添加您需要的任何组合,但最后,LoadMany返回一个列表,Load返回一个实体。

可能有例外,但除非您有很好的理由返回不同的类型,否则函数及其重载应该返回相同的类型,这样您就不会让其他开发人员发疯

例如:

var a = MyFunc("Some text");


对我来说,这两种方法都应该将var解析为相同的类型。在我偏离所有重载返回同一类型之前,我会确保返回一个非常不同的类型有一个非常坚实的理由。

无论如何,请考虑返回<代码> iQueaby而不是数组。Eric Lippert对此发表了一篇很好的博客文章。返回一个数组就足以突出该场景。我会在实际代码中返回一个IEnumerable。好的,很酷。只要你知道。但也意味着你的API中充斥着许多做同样事情的方法。此外,以其他人的API为例并不能帮助你理解他们以这种方式设计API的思维过程。我宁愿看到六个有思维过程的不同例子,也不愿看到一大堆没有思维过程的API。这样我就可以做出明智的决定,而不是盲目地追随别人的榜样。我不是一个盲目的追随者=)我写了我的观点,领先的技术至少值得我关注。顺便说一下,获取一个实体和获取多个实体不是一回事。这并不意味着你是一个盲从者,对不起。我只是把我的意见记录在案。如果从按透视图筛选的加载实体查看,则匹配一条记录的参数与匹配多条记录的参数没有什么不同。您知道筛选器只返回一条记录这一事实与您不知道的筛选器没有什么不同。关于参数,我理解您的观点,但我强调的是一个概念,而不是实际的代码路径。我想象在现实生活中,我会传递过滤信息,这些信息可能会返回项目列表,而不是单个项目。我喜欢多元化的想法,它肯定会让多个方法在智能意义上保持一致。公平地说,我没有考虑var透视图,这实际上违背了我的宗旨,即尽可能少地引用其他代码,使每一行都尽可能容易理解。
var a = MyFunc("Some text");
var a = MyFunc(1);