C# 函数与函数重载

c# 函数与函数重载
本章的学习重点:
  ◆    函数的概念
  ◆    函数的语法
  ◆    函数的调用及执行过程

4.1函数概念
  在数学领域,我们经常会听到函数的概念,比如三角函数中的正弦函数,余弦函数,正切函数,余切函数,这些对于我们来说,再熟悉不过了,只要输入相对应的变量就可以计算出结果。格式为y=f(x)。x称为自变元,y称为因变元,f称为函数名。
  今天,在计算机领域,也继承了这种思维方式,把一段经常需要使用的代码封装起来,在需要使用时可以直接调用,并且返回结果。格式为y=f(x)。x称为参数,y称为返回值,f称为函数名。同时,也再一次说明了计算机与数学的互补关系。

4.1.1函数的概念
  函数就是一段准备好的代码,它可以接受参数,处理逻辑,然后返回某些数据。我们通常使用函数来实现某个单一功能,通过对多个函数的组织和调用来实现整个程序的功能。函数相当于把一个复杂的较大的程序,分解为单一的较小的程序模块。所以,有时我们也把函数成为子程序。
在c#语言中,存在两种函数,一种是运行时提供的标准库函数,称为内置函数。这种函数不需要用户定义就可以直接使用。比如,console.write(),console.read()等函数。微软公司在开发.net平台的时候已经把我们在编写程序时经常需要使用的函数,以最优的方式编写好了,并以类库的方式提供给用户使用。用户使用时只需按内置函数给出的函数名和相关规则直接调用即可。
  另一种是用户自定义的函数,称为自定义函数。尽管内置函数能为程序设计提供方便,使程序的质量和效率得以提高,但其数量毕竟有限,不能完全满足用户的特殊需求。因此,c#语言允许用户按c#语言的函数语法自己设计函数,来实现更个性化的功能。
  作者心得:
  函数这一节很重要,可以说一个程序的优劣集中体现在函数上。如果函数使用的恰当,可以让程序看起来有条理,容易看懂。如果函数使用的乱七八糟,或者是没有使用函数,程序就会显得很乱,不仅让别人无法查看,就连自己也容易晕头转向。可以这样说,如果超过100行的程序中没有使用函数,那么这个程序一定很罗嗦(有些绝对,但也是事实)。

4.1.2函数的语法
  上一节,我们讲到了内置函数和自定义函数,内置函数比较简单只要知道函数的作用以及调用规则就可以顺利的使用了。内置函数的内部实现和自定义函数的实现是一样的,所以,我们只要理解了自定义函数,自然就明白了内置函数的使用方法。下面我们向大家介绍自定义函数的语法,简称函数的语法。
  一个函数包括函数头和语句体两个部分,语句体比较容易理解,就是指函数的内部实现。函数头由三个部分组成:返回值类型,函数名,参数表。格式如下:
 

 返回值类型 函数名(参数表)
  {
        语句体;
  }

  返回值类型用来定义函数返回的数据是什么类型的,可以是前面说到的某个内置数据类型、或者是自定义数据类型,在语句体中使用return关键字来返回数据。如果没有返回值,使用void关键字来代替具体的返回值类型。
  函数名用来代表函数的标识,所以在程序中必须是唯一的,不能重复定义。它也必须遵循我们在讲述变量时所讲的标识符命名规则。
  参数表用来向语句体传送外部数据,可以没有参数,也可以有多个参数。在函数调用的时候,参数可以是值类型,也可以是引用类型。语句体对值类型参数的修改不会影响函数外部的值类型数据。但是语句体对引用类型参数的修改会影响函数外部的引用类型数据。
  语句体可以申明局部变量,并且可以编写代码实现功能的逻辑。
  我们在前面其实已经接触过函数了,例如:console.writeline()函数,我们并不知道它的内部是什么,我们只要会使用它即可。下面我们来看一个范例:

using system;
namespace microsoft.example
{
    public class testfunction
    {
        static int add(int a, int b, int c)        //定义add函数
        {
            return a + b + c;                //返回值
        }
         static void main(string[] args)
        {
            int a = 1;        //定义int类型的变量a
            int b = 2;        //定义int类型的变量b
            int c = 3;        //定义int类型的变量c
            int result = add(a, b, c);            //调用add函数
            console.writeline("结果为:" + result);
        }
    }
}
  

上述代码中,第6行定义了一个add函数,其中int是它的返回值类型,add是函数名。这个函数需要输入三个整数a b c作为参数表。
  第8行是函数的语句体,用来实现函数的功能,这里实现的是三个整数相加。然后使用return关键字把结果返回调用函数的语句中。这里需要注意了,return关键字返回的类型要与函数名前面的回返值类型一致。
  最后的输出结果是:
  结果为:6
  作者心得:
  函数名的命名可大有学问,我们需要记住的第一条就是名称要有真实意义。看着函数名就知道,函数的作用是什么,实现什么功能。在c#语言中一般使用动宾格式来命名,而不是主宾格式。例如:getage()函数。

4.1.3函数的调用及执行过程
  上一节向大家讲述了如何定义一个函数,这一节将向大家讲述如何调用一个已经定义了的函数,以及函数调用的相关知识。
  函数的调用格式:
  函数名(参数表);
  需要说明一下,函数名必须与函数定义的函数名一致,这个估计大家不会做错。参数表也是一样,必须与函数定义的参数表一致,类型,个数,顺序都要一致。当多个参数时,使用逗号相互隔开。作为参数表中的参数可以是常量,有值的变量或者运算表达式。
  在c#语言中,函数调用根据在程序中出现的位置来分,可以有以下三种调用方式:
  1、以函数调用语句的形式调用。当函数调用不要求返回值时,可由函数调用加上分号构成来实现,即该函数调用作为一个独立的语句使用。
  例如:test();
  test()函数调用相当于执行一段相关程序。
  2、函数调用作为一个运算对象直接出现在一个表达式中。例如:
  k=sin(x)*cos(y);
  该赋值语句包含两个函数调用,每个函数调用都是表达式的一个运算对象。因此要求函数应带回一个确定的值参加表达式的运算,这种表达式称为函数表达式。
  3、将一个函数调用的返回值作为另一个函数调用的实参。例如:k=sin(cos(x));
  下面我们来看一个范例:

using system;
namespace microsoft.example
{
    public class testtransfer
    {
        static int add(int a, int b, int c)        //定义add函数
        {
            int sum;                    //定义一个int变量sum
            sum = a * (b + c);            //进行计算
            console.writeline("a的值为:" + a);
            console.writeline("b的值为:" + b);
            console.writeline("c的值为:" + c);
            return sum;                //返回值
        }
         static void main(string[] args)
        {
            int j, sum;                    //定义两个int类型的变量
            console.write("请输入j的值:");
            int.tryparse(console.readline(), out j);
            sum = add(j, ++j, ++j);        //调用add函数
            console.writeline("计算结果sum是:" + sum);
            console.write("请输入j的值:");
            int.tryparse(console.readline(), out j);
            sum = add(++j, ++j, j);        //调用add函数
            console.writeline("计算结果sum是:" + sum);
        }
    }
}
  

上述代码中,当输入j=1,调用函数add(j,++j,++j)时,按从左到右的顺序,先计算表达式的值,相
当于add(1,2,3)函数调用,函数计算返回值 1*(2+3)=5。
  当再次输入j=1,调用函数add(++j,++j,j)时,按从左到右的顺序,先计算表达式的值,相当于add(2,3,3)函数调用,函数计算返回值 2*(3+3)=12。
  这里需要注意的是,c#对于参数为表达式是,使用的是从左到右的计算顺序。其他语言可能有所不同,比如c语言使用的是从右到左的计算顺序。
  最后的输出结果是:
  请输入j的值:1
  a的值为:1
  b的值为:2
  c的值为:3
  计算结果sum是:5
  请输入j的值:1
  a的值为:2
  b的值为:3
  c的值为:3
  计算结果sum是:12

 

本章的学习重点:
  ◆    函数重载的概念
  ◆    函数重载的优点

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
      );
  }

  可以清楚地看到,如果没有这些重载来帮助设置默认参数值的话,用户需要多编写多少代码去完成一个本应该非常简单的操作

时间: 2024-09-26 12:53:30

C# 函数与函数重载的相关文章

PHP利用func_get_args和func_num_args函数实现函数重载实例_php技巧

本文实例讲述了PHP利用func_get_args和func_num_args函数实现函数重载的方法.分享给大家供大家参考.具体方法分析如下: 学习php的朋友都知道php本身是没有函数重载这一说的,更没说像java,c那样使用方法,但如果我们深入了解一下会发现可以在php中使用func_get_args()和func_num_args()函数实现函数重载,下面来举两个函数重载例子.这两个函数实现函数的重载. 1.默认参数,如果一个函数里面,这不是必须参数,而添加相应的默认值,就可以完成相应的功

c++ 函数模板重载-关于c++中函数模板的重载问题

问题描述 关于c++中函数模板的重载问题 直接上代码(简单),enter code here template< class T > void test(T x){ cout<<x<<endl; } void test(int); int main(){ int x = 1; test(x); } 上述程序使用非模板函数对函数模板test进行重载:按照书中的说法-这个非模板函数可以只声明原型,然后借用模板中定义的函数体. 但是链接的时候找不到那个非模板函数的定义(使用的

PHP利用func_get_args()和func_num_args()函数实现函数重载

这两个函数实现函数的重载!! 1.默认参数 从这个上面就可以看到,如果一个函数里面,对不是必须参数,添加相应的默认值,就可以完成相应的功能.  代码如下 复制代码   function overloadFun($param1, $param2 = '1',$param3 = true)   {    // do something   } 利用函数func_get_args()和call_user_func_array() PHP代码:  代码如下 复制代码 function rewrite()

PowerShell函数实现类似重载功能实例_PowerShell

本文介绍PowerShell自定义函数是否支持重载,如果支持,如何重载?如果不支持,如何实现与重载相似的效果? 郑重声明:PowerShell自定义函数不支持重载!也就是说,你不能定义两个同名的PowerShell函数,不管参数个数.顺序.类型是否相同.既然PowerShell自定义函数不支持重载功能,那么有没有什么办法来实现与重载相似的效果呢?有,当然有,那就是参数集(Parameters Set) PowerShell自定义函数的参数集是可以为一个函数定义一个参数集,在调用函数时可以从参数集

QObject成员函数connect()函数

1:首先要链接的两个类必须继承于QObject,同时添加 Q_OBJECT. 2:在qt中QObject::connect中填写的signal和slot函数,一定要填写参数类型.     因为类中的函数可以,也就是,重载函数名一样,参数不一样,如果QObject::connect中的函数没有参数类型,则无法正确连接. 3:QObject::connect中的signal 和 slot 函数一定要有参数类型, 但是,不可以有参数: You must use the SIGNAL() and SLO

函数声明和函数表达式——函数声明的声明提前

定义函数的方法 定义函数的方法主要有三种:     函数声明(Function Declaration)     函数表达式Function Expression)     new Function构造函数 其中,经常使用的是函数声明和函数表达式的函数定义方法,这两种方法有着很微妙的区别和联系,而且这两种方法的使用也容易混淆,所以这篇文章主要总结下这两种函数定义方法的相关知识点,当然本文的主题依然是关于函数提前的. 函数声明的典型格式: function functionName(arg1, a

谈函数指针(全局/类成员函数)和函数对象

函数指针(全局函数/类成员函数).函数对象(Function object) 一. 函数指针类型为全局函数. #include "stdafx.h"#include <iostream>using namespace std;class TestAction;typedef void (*fp)(int); void Drink(int i){ cout<<"No. "<<i<<" drink..."

wps表格函数及函数简单使用

  今天小编为大家介绍一下wps表格中常用的函数及函数简单使用方法. 一.函数应用基础 (一)函数和公式 1.什么是函数 WPS表格 函数即是预先定义,执行计算.分析等处理数据任务的特殊公式.以常用的求和函数SUM 为例,它的语法是"SUM( 数值 1, 数值 2,......)".其中"SUM"称为函数名称,一个函数只有唯一的一个名称,它决定了函数的功能和用途.函数名称后紧跟左括号,接着是用逗号分隔的称为参数的内容,最后用一个右括号表示函数结束.参数是函数中最复杂

(转载)JavaScript中匿名函数,函数直接量和闭包_javascript技巧

原文出处: http://www.dnew.cn/post/196.htm 先看下下面几种写法 1.function f(x){return x*x;};f(x); 2.(function(x){return x*x;})(x); 3.(function(x){return x*x;}(x)); 第一种我们应该都很熟悉了,这是我们经常使用的写法.第二第三种都是匿名函数的写法. ------------------------------------------------------------