方法

方法

方法的构成

一个方法由签名和方法体构成。其中,方法的签名包括方法的名称以及参数信息(包括形参的修饰符、数目、类型以及泛型参数的数目)。特别需要注意的是,返回值类型、形参和类型参数名称并不属于方法签名的一部分。

public int Add(int a, int b)
{
    return a + b;
}

其中形参列表中的a和b, public和返回值int并不属于方法签名, Add(int, int)才是方法签名

参数

命名和可选参数

public int Add(int a, int b = 1)
{
    return a + b;
}

int result1 = Add(1, 2); //3
int result2 = Add(1); //2

可选参数的规则:

  • 可选参数不能为参数列表第一个参数, 它必须位于所有必选参数之后
  • 可选参数必须指定一个默认值
  • 可选参数的默认值必须是一个常量表达式,不能为变量
  • 所有可选参数以后都必须为可选参数

命名参数示例

public int GetArea(int height, int width)
{
    return height * width;
}

int result = GetArea(width: 2, height: 3); //参数顺序无关

重载决策机制

M(string s, int i = 1);
M(object o);
M(int i, string s = "Hello");
M(int i);

M(5);

判断规则

  • 如果所有参数要么都可选, 要么有一个和参数类型兼容的参数(根据名称或位置)
  • 如果有多种选择, 重载决策机制优先选择为指定了具体值的重载, 而忽略那些没有为可选参数提供值的情况
  • 如果有两种选择待选, 则优先选择没有省略可选参数的重载
  1. M(string, int)被淘汰, 实参5不能被隐匿转换为string类型
  2. M(int, string)符合条件, 是待选之一, 它的第二个参数是可选的
  3. M(object) M(int)也是待选的重载
  4. M(int, string) M(int)要优于M(object), 因为5到int的转换要好于5到object的转换
  5. M(int)要优于M(int, string), 因为没有可选参数被省略
  6. M(int)最后被使用

四种类型的参数

按值传递参数

值参数是通过将实参的值复制到形参,来实现将值传递到方法,也就是我们通常说的按值传递。方法被调用时,CLR会

  • 在托管堆栈中为形参分配空间
  • 将实参的值复制到形参

形参为值类型时是将实参中的值(基本数据)复制到新的空间中,形参为引用类型时是将实参中的值(地址)复制到新的空间。

按引用传递参数--关键字(ref)

引用参数,也就是说,传递的是参数的引用而不是参数值

public void DoSomething(ref int someValue)
{
      someVaule = 10;
}
int x = 5;
DoSomething(ref x);

输出参数--关键字(out)

输出参数将值从方法内传递到方法外, 只有变量才有资格作为输出参数,文本值和表达式都不可以

int x = 5;
string s = “yy”;
DoSomething(ref x, out s);

Console.WriteLine(“x={0}, s={1}”, x, s);

public void DoSomething(ref int value1, out string value2)
{
    value1 = 10;
    value2 = “xx”;
}

针对引用传递参数和输出参数, 编译器允许在方法中的任意位置、任意时刻读取引用参数的值, 但禁止在为输出参数赋值前读取它。

参数数组--关键字(params)

参数数组类似于可选参数, 但也大有不同, 参数数组更加灵活

public void DoSomething(string str, params int[] values){}
DoSomething(“a”);
DoSomething(“a”, 1);
DoSomething(“a”, 1, 2);

int[] arr = { 1, 2, 3};
DoSomething(“a”, arr);

栈帧

栈帧也叫做过程活动记录, 是编译器用来实现方法调用的一种数据结构, 函数的调用堆栈包含:方法参数, 方法中的局部变量, 方法执行完后的返回地址, 获取文件中包含执行代码的行号和列号, 获取包含所执行代码的文件名

递归

递归的能力在于用有限的语句来定义对象的无限集合. 递归就是在方法里调用自身, 在使用递归策略时, 必须有一个明确的递归结束条件, 称为递归出口, 否则将无限进行下去.

使用递归程序的优点: 用递归的思想写出的程序往往十分简洁易懂

使用递归程序的缺点: 1.运行效率低, 2. 在递归调用的过程中,系统会为每一次调用生成新的栈帧,并使用栈来存储,因此递归次数过多容易造成栈溢出

方法的重载

在类中定义多个名称相同、签名(方法名、参数类型及个数、参数顺序及修饰符)不同的方法。需要注意的是,方法的返回值不属于签名的一部分。所以是否构成重载有以下几个条件:
1.在同一个类中 2.方法名相同 3.方法签名不同

静态方法

方法主要分为静态方法和实例方法,使用了static修饰符的方法为静态方法, 静态方法有如下特点:

  • 它不属于特定对象的方法, 它可以被一个类的具体实例访问
  • 它只可以访问静态成员变量, 而不可以直接访问实例变量
  • 它不用创建类的对象即可访问

静态方法中不能使用this关键字引用类的当前实例

参考引用

[1]: C# 权威指南

posted @ 2019-05-31 23:52  Allen2015  阅读(298)  评论(0编辑  收藏  举报