C#本质论6.0第四章:方法和参数

2021-07-05 01:13

阅读:594

标签:函数   它的   语言   默认值   相关   列表   重要   rand   方法调用   

方法和参数

方法组合一系列语句以执行特定操作或计算特定结果,它能够为构成程序的语句提供更好的结构和组织。

  • 方法总是和类型——通常是类关联。
  • 方法通过实参接收数据,实参由方法的参数或形参定义,参数是调用者用于向被调用的方法传递数据的变量。
  • 方法通过返回值将数据返回给调用者。

命名空间

命名空间是一种分类机制,用于组合功能相关的所有类型。

  • 作用:命名空间主要用于按照功能领域组织类型,以便更容易的查找和理解它们。除此之外还有助于防止类型名称发生冲突。

类型名称

调用静态方法时,如果目标方法和调用者不在一个类型中(或者目标方法不在基类中),就需要使用类型名称限定符。

作用域

一个编程元素的“作用域”是指可以通过它的非限定名称引用到它的区域。所以,在特定命名空间的某个类型中的方法调用不需要在方法调用名称中指定该命名空间前缀。

using指令

using指令可将一个或多个命名空间的所有类型“导入”一个文件。

  • using指令不会导入任何嵌套命名空间中的类型。嵌套命名空间必须显示导入。
  • 在命名空间顶部使用using指令只在声明的命名空间内有效。
  • using static指令允许省略规定类型的任何成员之前的命名空间和类型名称。
  • using指令可以为命名空间或类型取一个别名:using CountDownTimer = System.Timers.Timer

调用栈和调用点

每次调用一个新方法,“运行时”都调用一个栈帧,其中包含的内容涉及传给新调用的实参,新调用的实参、新调用的局部变量以及方法返回时应该从哪里恢复等。这样形成的一系列栈帧称为调用栈。随着程序复杂度提高,每个方法调用另一个方法时,这个调用栈都会变大。当调用结束时,调用栈会发生收缩,直到调用另一个方法。我们用栈展开描述从调用栈中删除栈帧的过程。方法调用完毕之后,执行会返回到调用点。

方法的参数

  1. 值参数
    参数默认是传值(pass by value)的,参数表达式的值会复制到目标参数中。调用栈在一次调用的末尾展开的时候,复制的数据会被丢弃。
  2. 引用参数ref
    传引用(pass by reference)的方式传递变量:使用ref关键字使被调用的方法可以用新值来更新调用者的变量。
    如果被调用的方法将参数指定为ref,那么调用者在调用这个方法的时候,提供的实参应该是附加了ref前缀的变量,而不是值。
    调用者应该对传引用的变量进行初始化,因为目标方法可能直接从ref参数读取数据而不先对其进行赋值。
  3. 输出参数out
    方法经常要获取一个变量引用,并且只向变量中写入而不从中读取,这时安全的做法是以传引用的方式传入一个未初始化的局部变量,用out修饰参数类型。
    C#语言对别名变量的读写有着不同的规定:如果参数被标记为out,编译器会核实在方法所有正常返回的代码路径(不抛出异常的代码路径)中,是否都对该参数进行了赋值。
    可用这个方式来克服方法只有一个返回类型的限制,但是这种做法并不好。

参数数组:

  • 当希望一个方法接受数量可变的参数时,请使用参数数组:
    1. 在方法声明的最后一个参数之前添加params关键字。
    2. 将最后一个参数声明为数组。像这样声明了参数数组之后,每个参数都作为参数数组的成员来访问。
  • 注意:
    • 参数数组不一定是方法的唯一参数,但必须是方法声明中的最后一个参数。也因此方法最多只能有一个参数数组。
    • 调用者可以指定和参数数组对应的零个实参,这会造成传递的参数数组包含零个数据项。
    • 参数数组是类型安全的——实参的类型必须兼容于参数数组中元素的类型。
    • 调用者可以显式的使用数组,而不是以逗号分隔的参数列表,最终生成的CIL代码是一样的。
    • 假如目标方法的实现要求一个最起码的参数数量,请在方法声明中显式指定必须提供的参数。即用int Max(int first, params int[] operands)代替int Max(params int[]operands )以确保至少有一个整数实参传给Max()

方法重载

假如一个类包含两个或者更多同名的方法,就会发生方法重载(overloading),重载的方法,参数的数量和数据类型不同。
可以用在一个方法中实现核心功能,其他重载的函数调用这个方法的形式来增强函数复用性。

方法重载是一种操作性多态,如果由于数据的变化导致一个逻辑操作具有许多形式,就会发生多态。

可选参数

声明方法时把常量值赋给参数,以后调用方法时就不必对每个参数都指定。
private int Attack(Gameobject target=player){}

  • 可选参数一定放在所有必须的参数后面。
  • 默认值必须是常量,或者说必须是能在编译时确定的值。

命名参数

通过显式的为一个参数赋值,而不是依据参数顺序来决定哪个值赋给哪个参数。
Attack(target: player)

  • 方法重载,可选参数以及命名参数这几种技术一起使用,将难以一眼看出最终调用的是哪个方法,只有在所有参数(可选参数除外)都恰好有一个对应的是惨,而且该实参具有兼容类型的情况下,才说一个调用适用于一个方法。为了进一步区分方法,编译器只使用调用者显式标识的参数,忽略调用者没有指定的所有可选参数。所以,假如由于一个方法有可选参数,导致两个方法都适用,编译器最终选择的是无可选参数的方法。
  • 当编译器必须从一系列适用的方法中选择一个最适合某个特定调用的方法时,会选择拥有最具体参数类型的那个方法。假如有两个适用的方法,每个都要求将实参隐式地转换成形参的类型,最终选择的是形参类型是更具体的派生类型的那个方法。

用异常实现基本错误处理

方法利用异常处理将有关错误的信息传给调用者,同时不需要使用返回值或者显式提供任何参数。为了通知调用者参数无效,程序会引发异常,中止执行当前分支,跳到调用栈中用于处理异常的第一个代码块。对错误进行恰当的处理过程被称为捕获异常

try与catch关键字:

  • try表示块中的代码可能引发异常,如果真的引发了异常,那么某个catch块要尝试处理这个异常。
  • try块之后必须紧跟着一个或多个catch块。catch 块可选择指定异常的数据类型,只要数据类型与异常类型匹配,对应的catch块就会执行。
  • 处理异常的顺序非常重要,catch块必须按照从最具体到最不具体排列。
  • 无论如何离开try块,finally块都会执行,其作用是提供一个最终位置,在其中放入无论是否发生异常都要执行的代码。其最适合用来执行资源清理。
  • 常规catch(不接受任何参数):等价于获取object数据类型的catch块。由于所有类最终都从object派生,所以没有数据类型的catch块必须放到最后。

throw关键字:

  • C#允许开发人员从代码中引发异常。如果引发一个异常,会使执行从异常的引发点跳转到与引发的异常类型兼容的第一个catch块。

  • 有时catch块能捕获到异常,但不能正确或完整的处理它。在这种情况下,可以让这个catch块重新引发异常,具体的方法是使用一个单独的throw 语句,不要在它后面指定任何异常。

C#本质论6.0第四章:方法和参数

标签:函数   它的   语言   默认值   相关   列表   重要   rand   方法调用   

原文地址:https://www.cnblogs.com/zhang-mo/p/9834057.html


评论


亲,登录后才可以留言!