{18} C # learning pass, the output, a reference array, named, optional parameters, extension method

Pass parameter value (parameter value)

1. The value of the parameter defined pass

Here Insert Picture Description
Create a copy of the value of the variable parameters, the operation of the value of the parameter will never affect the value of the variable

2. The value of the parameter passed value type

Here Insert Picture Description

Code Example
Here Insert Picture Description
Description:
(1) create a first class Student, The AddOne create a () method of the class, the process parameter is int x, pass a value type parameter (int 32 is the structure type, and declare this parameter did not take any modifier), the logic of the method is applied to an argument passed in value, and then printed out

(2) create an instance of the Student class, and references to variables stu

(3) declare a variable int y, 100 assigned to y

(4) The AddOne call instance method (), the variable y is passed as an argument method ( since the initial value of the transfer parameter values from the method invokes the appropriate arguments provided, the value of the parameter initial value 100 ), the program jumps to the internal operation method

(5) However,Since the value of the parameter will create a copy of variables, operations on the value of the parameter will never affect the value of the variable, So after the method call, a new parameter value, and the value of the variable y has not changed

3. The reference type by value parameters (create a new object)

Here Insert Picture Description
图解:
(1)首先明确:引用类型的变量引用着引用类型的实例,引用类型变量存储的值,是引用类型实例在堆内存当中的地址

(2)当把一个引用着实例的引用类型的变量作为参数传进方法之后,会产生一个副本,该副本存储的值显然也是一个地址;也就是说:该副本(方法的参数)所存储的地址和方法外部的变量所存储的地址实际上是同一个地址,指向同一个对象

(3)如果在方法内部为参数赋了新值,也就是把一个新对象交给参数去引用,强调:由于值参数创建变量的副本,对值参数的操作不会影响变量的值,所以方法外部的变量还引用着先前的那个对象
(一把情况下,为引用类型变量赋值时,赋值符号右边都是new操作符的表达式;new操作符的作用:根据数据类型创建对象,并且调用对象的实例构造器,然后把实例在堆内存上的地址通过赋值符号交给引用变量)

代码示例
Here Insert Picture Description
说明:
(1)创建一个Student类,为该类声明一个Name属性,在创建该类的实例时可以初始化Name属性的值

(2)声明一个静态方法SomeMethod(),该方法的传值形参 “stu” 的数据类型是引用类型,该方法的逻辑是:创建Student类的实例,将其Name属性的值初始化为 “Tom”,然后打印出来

(3)在Main()方法中声明一个引用类型的变量 “stu” ,其引用着一个Student类的实例,该实例的Name属性值被初始化为 “Tim”

(4)调用SomeMethod()方法,并将声明的变量 “stu” 作为实参传入进去

(5)再次强调:传值参数创建变量的副本,对值参数的操作永远不影响变量的值,所以方法运行的结果是打印出 “Tom”,而变量 "stu"的属性依然是 “Tim”

4.小知识:GetHashCode()方法

如果在方法体内部创建的实例的Name属性值也是 “Tim”,这时该如何分辨变量和参数引用的实例是否是同一个呢?
Here Insert Picture Description
结果都为 “Tim”,不能再根据对象的Name属性值分辨出来参数和实例引用的是两个不同的对象,此时就需要用到GetHashCode()方法;该方法是Object类的方法,但由于所有类都是Object类直接或间接的派生类,所以所有类型都具有GetHashCode()方法
当调用该方法时,会得到一个代表对象的唯一值,即每个对象的HashCode都不一样
Here Insert Picture Description

5.初学者常见的两个疑惑

(1)方法的参数名叫 “stu”,方法外部的变量名也叫 “stu”,是否在调用该方法时传入的变量(实参)的名字和参数(形参)的名字必须一样呢?
答:不需要一样,注意对应即可
Here Insert Picture Description

(2)方法外部的变量 “stu”,和方法内部的参数 “stu” 不会冲突吗?
答:不会,因为它们两个的作用域完全不同;前者的作用域是在Main()方法体中,而后者的作用域是在SomeMethod()方法体中

6.引用类型的传值参数(不创建新对象,只操作对象)

Here Insert Picture Description
图解:
(1)当引用类型的变量以传值参数的形式传进方法,此时参数的值和传进来的变量的值是同一个值:也就是对象在堆内存中的地址

(2)接着,通过参数访问了由参数所引用的对象,并修改了对象中的某个值;此时会发现:由于变量和参数指向的是同一个对象,通过参数修改了对象的值,那么当尝试用变量去访问该对象的值时,拿到的也是更新之后的值

代码示例
Here Insert Picture Description

待解问题:传值参数不是创建变量的副本,对副本操作而不会影响变量本身吗?为什么在这种情况下变量所引用的对象的值还是会改变?

7.提醒

(1)第3点:像这种通过值参数把一个引用类型变量传进来,再把该变量先前所引用的对象抛弃掉,而在方法内部创建一个新的对象,这种操作在平时的编程当中并不常见
因为一般情况下,对于传进来的参数,我们只是读取它的值
(2)第6点:通过值参数把一个引用类型变量传进来并修改该变量所引用的对象的值的情况也是很少见的
因为作为一个方法而言,它的主要输出还是靠它的返回值;这种操作一般称为某个方法的副作用(side-effect),基本上是要注意避免的

输出参数

  • 可以把方法当做一个数据加工厂,方法的参数——加工厂的原料;方法的返回值——加工厂的产品;
  • 方法的返回值只有一个,如果希望一个方法一次调用能够产出多个数据时,就需要用到输出参数了;
  • 带有输出参数的方法一定具有副作用,而且我们是有意利用这个副作用:通过输出参数,来获得除返回值之外的额外的输出利用引用参数的副作用是打算修改传进来的那个值(因而也就可以理解为什么引用参数在传进方法之前必须要有一个明确的赋值:如果不提前赋值,那你修改个锤子?)

1.输出参数的定义

输出参数也不会为传进来的实参创建副本,输出形参与实参指向的是同一个内存位置
Here Insert Picture Description
输出形参的作用是通过该参数向外输出,那么原来赋的值也就会被丢弃,也就没什么意义了;所以C#并不要求输出参数在传入方法之前要明确赋值,相反,由于输出参数是为了把值从方法体内输出到方法之外,所以在方法体内就必须对其有明确赋值

2.值类型的输出参数

Here Insert Picture Description
图解:
(1)值类型的变量以输出参数的形式传进方法,输出参数和变量指向的内存地址是同一个;注意:作为输出参数传进方法的变量的初始值可有可无

(2)在方法体内为输出参数进行赋值,由于输出参数和外部变量指向的是同一内存地址,所以变量也获得了新值

3.调用带有输出参数的方法

在C#的类库当中,有些类型已经有了带有输出参数的方法,比如 int类型,double类型;在这里用double类型的TryParse()方法示例
Here Insert Picture Description

4.声明带有输出参数的方法

Here Insert Picture Description

5.引用类型的输出参数

Here Insert Picture Description
图解:
(1)把引用类型的变量以输出参数的形式传进方法,输出参数不为变量创建副本,参数和变量指向同一个地址;输出参数的初始值可有可无

(2)对于一个引用类型的变量来说,如果它有初始值,则该变量引用着堆上的一个对象;如果没有初始值,则说明该变量没有引用任何对象

(3)如果在方法体内为输出参数赋了新值,也就是说把一个新对象的地址交还给输出参数,那么由于变量和参数指向的是同一个地址,所以变量所引用的内存地址也被更新,指向了新对象

代码示例:
Here Insert Picture Description

引用参数

1.引用参数的定义

Here Insert Picture Description
引用参数不会为传进来的实参创建副本,它直接指向传进来的实参所指向的内存地址
当调用带有引用参数的方法时,作为实参所传进来的变量,之前一定要有明确的赋值,而且,在调用时,引用参数前也要加 “ref” 关键字(起提示作用:此方法的副作用是改变实参的值)

2.值类型的引用参数

Here Insert Picture Description
图解:
(1)有一个值类型的变量,具有初始值;然后以引用参数的形式将其传进方法,但是要注意:引用参数并不为传进来的变量创建副本

(2)在方法内部为引用参数赋了新值,由于引用参数和变量指向的是同一个地址,所以当参数获得了新值以后,方法外部的变量同时也获得了新值

代码示例:
Here Insert Picture Description
说明:
方法的参数x与方法外部的变量y所指向的是同一个内存地址,当我们在方法内部改变了这个地址上的值的时候(x = x + 100),方法外部的变量y所指向的内存地址上的值也就改变了,所以当通过外部的变量y来访问内存地址中的值时,拿到的就是更新之后的值

3.引用类型的引用参数(创建新对象)

Here Insert Picture Description
图解:
(1)有一个引用类型的变量引用着一个实例,把该变量以引用参数的形式传进方法;传进之后,引用参数并不会为该变量创建副本,引用参数和变量指向的是内存中的同一个地址,该地址中存储的是实例在堆内存上的地址

(2)在方法体中为参数赋了新值,也就是把一个新的对象交由参数引用,由于引用参数和变量指向的是内存中的同一个地址,所以此时方法外部的变量也指向了新创建的对象

代码示例:
Here Insert Picture Description

4.引用类型的引用参数(不创建新对象,只改变对象值)

Here Insert Picture Description
在方法体内并没有为引用类型赋新值,而是只通过引用参数去访问它所引用的对象,并改变了对象中的值;注意:此时对象并不是一个新对象,其HashCode并没有改变,改变的只是对象内部的字段或是属性的值
Here Insert Picture Description

在这种情况下使用引用参数和使用传值参数效果是一样的,只是内存机理不一样

  • 如果在IWantSideEffect()方法中使用传值参数,那么传值参数就会在内存中创建实参的副本,也就是说:参数 “stu” 和变量 “outterstu” ,它们两个所指向的内存地址是不一样的,但这两个不一样的内存地址中,却存储着相同的地址——即实例在堆内存中的地址
  • 但如果在IWantSideEffect()方法中使用引用参数,参数 “stu” 和变量 “outterstu” ,它们两个所指向的内存地址就是完全一样

数组参数

Here Insert Picture Description

1.为什么需要数组参数

  • 如果不用数组参数,要求一个数组的和,需要这样写代码:
    Here Insert Picture Description
  • 如果用数组参数,就不用了再提前声明一个数组,在调用该方法时传入数组元素即可
    Here Insert Picture Description
    当编译器发现是 “params参数” 时, 会自动声明一个数组,并把给出的元素放进数组,再传进方法

2.其实早就已经见过数组参数

(1)String.Format方法

int x = 100;
int y = 50;
int z = x + y;
Console.WriteLine("{0} + {1} = {2}",x,y,z)

(2)String.Split方法

string str = "Tom;Tim,Alice.Amy";
string[] result = str.Split(';',',','.');
foreach (var item in result)
{
	Console.WriteLine(item);
}
//Split()方法的返回值是字符串数组类型

3.使用数组参数需要注意

在一个方法的参数列表中,只能有一个参数是 params 数组参数,且必须是参数列表中的最后一个参数;否则,编译器会无法判断哪些参数是数组参数

具名参数

当调用一个方法时,传进去的参数是带有名字的

1.代码示例

Here Insert Picture Description

2.具名参数的优点

(1)提高代码可读性
(2)参数的位置不再受参数列表顺序的约束
严格来说,具名参数并不是参数的某个种类,而是参数的使用方法

可选参数

Here Insert Picture Description
可选参数:当调用方法时,该参数可写可不写;因为在声明方法时该参数是具有默认值的
代码示例:

static void Main(string[] args)
{
	Print();
}
static void Print(string Name = "Bob",int Age = 23);
{
	Console.WriteLine("{0} is {1} years old!",Name,Age);
}

扩展方法(this参数)

Here Insert Picture Description

1. Why do you need an extension method?

double x = 3.14159;
double y = Math.Round(x,4);
//double类型没有round()方法,必须要调用 Math的round()方法

How to make a double with a round () methods?
A naive approach is to modify the source code, but this is impossible; first of all, can not get the source code, secondly, even if got, and complete the modification can not compile the results into the C # class library which
case, it We need to use extension methods, a statementStatic class, The use of such a double extension, the convention, the class name should be "DoubleExtension" (SomeTypeExtension)

Code Example 2

Here Insert Picture Description
Note that the icon is an extension method: Methods black icon with a small down arrow

When we can not modify a type of source code, you can use extension methods for such additional target data type methods , C # has many important functions are based on extension methods, such as: Language Integrated Query: LINQ method

3. What is LINQ?

A method is also known LINQ integrated query language, very powerful
example:
logic to be achieved: judging whether or not the value of a set of greater than 10

  • If you do not LINQ method, you need to write a method
    Here Insert Picture Description

  • If you use LINQ method, you only need to write the code
    Here Insert Picture Description

Various parameters are summarized usage scenarios

Here Insert Picture Description

Published 29 original articles · won praise 3 · Views 942

Guess you like

Origin blog.csdn.net/weixin_44813932/article/details/103967564