热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#基础之参数(一)值参数、引用参数与输出参数

要学会各种参数,重点是理解参数参数传递的内存原理。理解了内存,各种参数使用的作用、效果等便可以自己分析出来,而不用死记硬背。1.按值传递参数(值参数)值参数是最常见的一种参数,也很

  要学会各种参数,重点是理解参数参数传递的内存原理。理解了内存,各种参数使用的作用、效果等便可以自己分析出来,而不用死记硬背。  

  1.按值传递参数(值参数)

    值参数是最常见的一种参数,也很好判断。在方法声明与调用时,参数前不加ref或out关键字的参数,便是按值传递。
    值参数是将实参变量在“栈”中存储的值复制一份副本,将副本传递给方法的形参。
    按值传递参数又分为两种不同情况:传递值类型,与传递引用类型
    (注意这里的值类型、引用类型是数据类型,而值参数、引用参数是参数传递方式。二者不是同一概念,不可混淆。)

    (1)传递值类型参数

    示例:

 1 class Program
2 {
3 static void Main(String[] args)
4 {
5 int a = 4;
6 int b = 5;
7 Add(a, b);
8 Console.WriteLine($"a={a},b={b}");
9 }
10 public static void Add(int x, int y)
11 {
12 x += 1;
13 y += 1;
14 }
15 }

    输出为:

a=4,b=5

    内存原理:在Add方法中对形参x与y的操作,并不会对实参a与b的值产生影响,因为在Add方法中操作的是a与b的副本。

    (2)传递引用类型参数 

    示例1:

 1 class Program
2 {
3 static void Main(String[] args)
4 {
5 Animal a = new Animal() { Age = 1 };
6 Add(a);
7 Console.WriteLine($"a.Age={a.Age}");
8 }
9 public static void Add(Animal animal)
10 {
11 animal.Age += 1;
12 }
13 }
14 class Animal
15 {
16 public int Age { get; set; }
17 }

    输出为:

a.Age=2

    内存原理:

    在Add方法中形参animal拿到了实参a在栈中的副本,副本中存储着对象的地址。所以,animal与a指向了同一个对象。
       这时操作的不是副本,而是副本所指的对象,即操作a所指对象。

    示例2:

    

 1 class Program
2 {
3 static void Main(String[] args)
4 {
5 Animal a = new Animal() { Age = 1 };
6 Add(a);
7 Console.WriteLine($"a.Age={a.Age}");
8 }
9 public static void Add(Animal animal)
10 {
11 animal = new Animal() { Age = 10 };
12 animal.Age += 1;
13 }
14 }
15 class Animal
16 {
17 public int Age { get; set; }
18 }

    输出为:

a.Age=1

    内存原理:

    与示例1不同的是,在示例2中Add方法中改变了animal所指向的对象,指向一个new的Animal对象,此时a仍指向原对象,这时再对animal进行操作,
       便不再会影响实参a所指的对象。

  2.按引用传递参数(引用参数)

     形参与实参之前,都要加ref关键字。
     需要注意的是,实参在使用之前必须赋值,否则编译器会报错。(如下图)
     此时不再复制实参在栈中的副本,而是将实参在栈中的地址传给形参,也就是实参与形参共用栈中的值。此时在方法中对形参所做的任何操作,都会影响实参。
     按引用传递也分为值类型和引用类型两种情况。

    (1)传递值类型参数

    示例:

    

 1 class Program
2 {
3 static void Main(String[] args)
4 {
5 int a = 4;
6 int b = 5;
7 Add(ref a, ref b);
8 Console.WriteLine($"a={a},b={b}");
9 }
10 public static void Add(ref int x, ref int y)
11 {
12 x += 1;
13 y += 1;
14 }
15 }

 

    输出为:

a=5,b=6

    内存原理:

    由于a与x,b与y指向了栈中相同的地址,在Add方法中对形参x与y的操作,会影响实参a与b的值。

    (2)传递引用类型参数

    示例1:

 

 1 class Program
2 {
3 static void Main(String[] args)
4 {
5 Animal a = new Animal() { Age = 1 };
6 Add(ref a);
7 Console.WriteLine($"a.Age={a.Age}");
8 }
9 public static void Add(ref Animal animal)
10 {
11 animal.Age += 1;
12 }
13 }
14 class Animal
15 {
16 public int Age { get; set; }
17 }

 

    输出为:

a.Age=2

    内存原理:

    这时得到的效果,与按值传递参数是一样的,但内存原理却不相同。

    这时Add方法中形参animal指向的不再是实参a在栈中的副本的地址,而是与a指向了栈中相同的位置。

    示例2:

 1 class Program
2 {
3 static void Main(String[] args)
4 {
5 Animal a = new Animal() { Age = 1 };
6 Add(ref a);
7 Console.WriteLine($"a.Age={a.Age}");
8 }
9 public static void Add(ref Animal animal)
10 {
11 animal = new Animal() { Age = 10 };
12 animal.Age += 1;
13 }
14 }
15 class Animal
16 {
17 public int Age { get; set; }
18 }

    输出为:

a.Age=11

    内存原理:

     这个示例便可以看出与按值传递时示例2的不同。

     Add方法中改变了animal所指向的对象,指向一个new的Animal对象,此时a所指向的对象也随之改变。这是由于形参animal
     与实参a指向的是栈中相同的地址(这个地址中存储的是对象在堆中的地址)。当栈中存储的堆地址改变时,animal与a会同时指向新的对象。

  3.输出参数

    用法:
     (1)形参与实参之前,都要加out关键字。
     (2)输出参数主要是用于函数需要有多个返回值时,作为返回值使用。
    与引用变量相同的是:
     (1)输出参数也不复制实参在栈中的副本,而是将实参在栈中的地址传给形参。在这点上,输出参数与引用参数相同。
     (2)实参必须是可以赋值的变量,而不能是常亮。
    与引用参数不同的是:
     (1)实参在使用之前不必赋值。
     (2)事实上,在使用之前对实参的赋值没有任何意义,因为在调用方法的最开始,便会将其值抹去,使其成为未赋值的变量。
     (3)在方法返回之前,必须对out参数进行赋值。
    由以上特点所决定的是,输出参数无法向方法中传递信息,其唯一作用便是,当一个参数需要返回多个值时,作为返回值返回。

    示例1:

 1 class Program
2 {
3 static void Main(String[] args)
4 {
5 int a;
6 Add(1, 2, out a);
7 Console.WriteLine(a);
8 }
9 public static bool Add(int x, int y, out int result)
10 {
11 result = x + y;
12 return true;
13 }
14 }

    输出为:

3

    引用类型的输出参数同理,请自行编写示例代码。

 

 请继续阅读参数学习的下篇:C#基础之参数(二) 数组参数、可选参数与命名参数

 

 

    


推荐阅读
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了在Java中gt、gtgt、gtgtgt和lt之间的区别。通过解释符号的含义和使用例子,帮助读者理解这些符号在二进制表示和移位操作中的作用。同时,文章还提到了负数的补码表示和移位操作的限制。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
author-avatar
风之淡然1_925
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有