函数重载与可选参数

Posted

技术标签:

【中文标题】函数重载与可选参数【英文标题】:Function overloading vs Optional Parameters 【发布时间】:2013-05-23 06:20:47 【问题描述】:

所以我只是在考虑函数重载...

重载的方法共享相同的名称但具有唯一的签名。参数数量、参数类型或两者必须不同。不能仅根据不同的返回类型重载函数。

那么在下面的示例中,为什么要重载setName 而不是对中间名和姓氏值使用可选参数?

class funOverload

    public string name;

    //overloaded functions
    public void setName(string last)
    
        name = last;
    

    public void setName(string first, string last)
    
        name = first + "" + last;
    

    public void setName(string first, string middle, string last)
    
        name = first + "" + middle + "" + last;
    

    //Entry point
    static void Main(string[] args)
    
        funOverload obj = new funOverload();

        obj.setName("barack");
        obj.setName("barack "," obama ");
        obj.setName("barack ","hussian","obama");

    

至少,使用以下代码会减少需要编写的代码量:

public void setName(string first, string middle = "", string last = "")

   name = first + "" + middle + "" + last;

   // name = "barack" + "" + "";


//Entry point
static void Main(string[] args)

    funOverload obj = new funOverload();

    // could optionally set middle and last name values here as well
    obj.setName("barack");
 

我了解重载的概念,但我不明白为什么它比使用可选参数更理想(反之亦然)。

谁能解释一下?

仅供参考,这是我重载的第一个函数:http://pastebin.com/ynCuaay1 这个函数允许你调用mysqlContext.GetReader() 有或没有参数列表...我认为它使代码比一直调用GetReader(sql, args.ToArray()) 更简洁

【问题讨论】:

视情况而定,可选参数适用于以前重载的东西,只是用额外参数的默认值调用它。在这里它们会适合,但有些地方不适合(例如,在内部使用 XmlWriter 但可以使用 TextWriter 的东西),例如 XDocument.Save 谁说一个比另一个更受欢迎?我认为这只是上下文和偏好的问题。 除了其他的cmets,可选参数直到c# 4.0才可用,我们这些在早期版本中学习的人已经习惯了编写重载函数。 可选参数更适用于存在合理或常见默认值的情况。而重载表明您实际上有多种形式的相同函数,具体取决于某些参数信息的存在。在大多数情况下,任何一种都可以,但在给定的上下文中,一种可能比另一种更清晰。 还有好玩的花絮;可选参数在编译时解析。因此,如果您针对具有 string middle = "" 的 DLL 进行编译,然后将其换成具有 string middle = null 的更新版本,而无需重新编译,您仍然会输入一个空字符串。同样,当涉及到继承/接口时,也没有任何虚拟/签名。如果声明MyInterface.Foo(string x = null),则实现可以声明MyClass.Foo(string x = "default"),调用者将根据对象的已知类型编译/传入一个值。 【参考方案1】:

我不明白为什么它比使用可选参数更理想

具有默认值的参数有一些限制,在某些情况下可能很重要。

你可以为引用类型设置默认参数,除了null(string参数除外):

class Foo

    public int Id  get; set; 


class Bar

    public Bar(Foo parent)
    
    

    public Bar()
        : this(new Foo  Id = 1 ) // this can't be done with default parameters
    
    

具有默认值的参数不能出现在常规参数之前,虽然这有时是合适的:

class Foo

    public void Method(int i, string s, bool b)  
    public void Method(string s, bool b) 
    
        Method(0, s, b); // this can't be done with default parameters
    

【讨论】:

【参考方案2】:

在您的示例中,三个重载并不等同于带有可选参数的方法。 setName(string last) 声明给出的最小数据是姓氏,而public void setName(string first, string middle = "", string last = "") 不允许您省略名字。如果您想在使用可选参数的方法调用中省略中间名,则必须有setName("barack", last: "obama")

有这样的可选参数的方法会更好:

public void setName(string last, string first= "", string middle = "")

但这会破坏名称的自然顺序,并允许您设置中间名而不先指定三个重载禁止的 (setName("barack", middle: "hussein");)。

【讨论】:

以上是关于函数重载与可选参数的主要内容,如果未能解决你的问题,请参考以下文章

C#4.0中的方法重载与可选参数[重复]

argparse 必需参数列表与可选参数列表竞争

可选函数参数:使用默认参数(NULL)还是重载函数?

基于可选参数存在而不使用函数重载的打字稿函数返回类型

Swift:如何将 for-in 循环与可选参数一起使用?

可选参数后的重载