现在的位置: 首页 > 综合 > 正文

《Visual C# 最佳实践》第四章 函数 (三):函数重载

2013年05月31日 ⁄ 综合 ⁄ 共 3685字 ⁄ 字号 评论关闭
文章目录

第四章 函数

  很多人到现在还分不清楚什么是函数,什么是方法,非常之困惑。其实,这两种概念是换汤不换药,讲到都是同一种东西。方法是面向对象的产物,比如,我们说使用某的对象的某个方法;函数是面向过程的产物,比如,我们经常会说执行某个函数。不管是函数还是方法,它们的写法都是一样的。本章将向大家详细介绍函数的相关概念。
  本章的学习重点:
  ◆    函数重载的概念
  ◆    函数重载的优点

4.3函数重载

  函数重载(Overload)为程序开发提供了极大的便利,尤其是对于我们这些类库的使用者——可以从复杂的类型转换中解放出来,只要以我们自己认为最方便的方式调用方法即可。本节主要从重载的语义角度来讨论与使用重载相关的一些基本条件。

4.3.1函数重载的概念

  函数重载是指多个函数实现可以同时使用一个函数名,只是函数的参数表不同而已。打个比方,使用重载函数我们可以定义多个加法函数来求两个数之和。其中,一个函数实现两个int类型之和,另外一个实现两个float类型之和,再另外一个实现两个decimal之和。每种实现对应一个函数体,这些函数的名字相同,但是函数的参数类型不同,这就是函数重载的概念。
  刚才我们说函数重载时多个函数使用同一个函数名。那么,C#语言的编译器就需要确定用户调用的是哪一个函数,即采用哪个函数实现。确定函数实现时,要求从函数参数的个数和类型上来区分。这就是说,进行函数重载时,要求同名函数在参数个数上不同,或者参数类型上不同。否则,将无法实现重载。
  函数重载的格式如下:
  void add(int a,int b)
  {}
  void add(int a,int b,int c)
  {}
  char add(char a,char b,char c)
  {}
  上述格式中,定义了3个add函数,第一个add()函数对应的是两个int类型求和的函数实现,而后边一个add()函数对应的是三个int类型求和的函数实现,最后一个add()函数对应的是三个char类型求和的函数实现,这便是函数的重载。
  下面我们来看一个范例:
using System;
namespace Microsoft.Example
{
    public class TestReturnValue
    {
        static int Max(int x, int y)                //定义int版本的Max函数
        {
            int z;
            z = x > y ? x : y;                    //比较x,y的大小
            return z;
        }
        static double Max(double x, double y)    //定义double版本的Max函数
        {
            double z;
            z = x > y ? x : y;                //比较x,y的大小
            return z;
        }
        static void Main(string[] args)
        {
            int intX = 50;                    //定义一个int变量
            int intY = 43;                    //定义一个int变量
            Console.WriteLine("比较两个整数的大小:" + intX + "; " + intY);
            int intResult = Max(intX, intY);        //调用int版本的Max函数
            Console.WriteLine("结果是:" + intResult);
            double doubleX = 50.5;                //定义一个double变量
            double doubleY = 43.3;                //定义一个double变量
            Console.WriteLine("比较两个整数的大小:" + doubleX + "; " + doubleY);
            double doubleResult = Max(doubleX, doubleY);        //调用int版本的Max函数
            Console.WriteLine("结果是:" + doubleResult);
        }
    }
}
  上述代码中,第6行我们定义了一个int版本的Max函数,这个函数只接收两个int类型的参数,然后返回int类型的数据。第12行我们定义了一个double版本的Max函数,这个函数只接收两个double类型的参数,然后返回double类型的数据。这两个函数使用了Max的函数名字,但是,它们能共同存在,这就是函数重载。
  最后的输出结果是:
  比较两个整数的大小:50; 43
  结果是:50
  比较两个整数的大小:50.5; 43.3
  结果是:50.5

4.3.2函数重载的优点

  从上面的范例中,我们可以知道,虽然不同的重载在形式上是多个独立的函数,但在语义上它们代表的是同一个函数——准确地说,它们执行的是同样的操作。之所以函数要提供多个重载,其主要目的是方便调用者。具体地说来包括以下一些优点:
  1、支持多种数据类型
  前面关于Max函数的范例即是说明了这一点。我们要提供的是“取最大值”的功能,并不是“对整型数取绝对值”的功能,因此将输入参数限制为整型是不合适的。提供重载可以使得用户不必操心有关数据类型转换的工作,各个重载函数会负责针对不同的数据类型进行处理,也减少了记忆。
  2、支持多种数据提供方式
  这是比支持多种数据类型更为宽泛而方便的方式。Int类型与double类型之间可以直接转换,但很多情况却没有那么简单。例如XmlDocument类提供了Load方法用于装入一个XML文档,那么如何指定这个文档呢?如果这个文档还没有被打开,那么指定它的路径及文件名是最方便的。如果这个文档已经打开,那么也许可以通过一个Stream对象对其进行访问是最方便的。对于类库的使用者来说,这些可能都是存在的,如果XmlDocument强制使用一种方式,无疑会给用户造成不便,此时最好的办法就是提供一组重载:
  XmlDocument.Load(string)
  XmlDocument.Load(Stream)
  这里的string、Stream之间是不存在类型转换关系的,重载函数要做的额外工作并不像之前那个最大值函数那么简单。但是对于函数的使用者来说,它们的意义是类似的。
  3、为复杂的参数提供默认值,简化调用
  这也是非常常见的情况。有些函数的功能非常强大,但其带来的负面影响就是函数调用者需要考虑太多的参数设置。事实上,大多数情况下,使用者真正关心的只是其中的一两个参数,剩余的参数都集中在某些相同的设置值上。如果能为这些高级特性提供合理的默认值的话,函数调用者的工作量就会大大降低。例如File的Create方法用于创建一个文件,它支持很多丰富的设置参数:
  public void Create(
      string path;
      int buffersize;
      FileOptions options;
      FileSecurity fileSecurity;
  }
  这么多设置参数,我们第一次创建文件的时候肯定会不知所措,按我们的理解,只要指定文件地址就够了。就像下面这样:
  public void Create(
      string path;
  }
  事实上Create确实提供了这样一个简单版本的重载,确实在大多数情况下,用户只需要一些简单的功能,那些复杂的特性被使用的频率相对较低。如果每次都要调用者设置这么多参数的话,显然增加了很多不必要的劳动。如果提供一个简单版本的重载,为这些高级特性提供合理的默认值的话,可以在很大程度上使代码变得更加简洁有序。前面这个重载函数,或许就是通过下面的方式来实现的:
  public void Create (string path)
  {
      Create (
      path;
      0
      FileOptions.None
      null
      );
  }
  可以清楚地看到,如果没有这些重载来帮助设置默认参数值的话,用户需要多编写多少代码去完成一个本应该非常简单的操作。
  作者心得:
  从之前所述的重载语义中,我们不难发现,函数的各个重载之间的区别仅在于对入口参数进行的预处理,其核心功能都是一致的。如果每个重载都单独编写的话,必然会产生大量的冗余代码,不但增加了编写代码的工作,也给日后的修改维护造成极大的困难。既然提供重载只是为了处理不同的入口参数形式,那么各个重载函数的工作也就应该是对参数进行处理,核心功能应该只由一个函数实现,其他所有重载都调用这个函数。

抱歉!评论已关闭.