zoukankan      html  css  js  c++  java
  • C#阶段提高之交换数值

           最近在从事两年前学过的C#语言工作,对于第三门接触的编程语言(第一门当然是是C语言、第二门是汇编),好多知识随时间的流过都变得不是那么熟练,刚好趁此机会学习巩固基础,厚积薄发。在此记下笔记也是想C#入门的同学参考,怎样在.NET的道路上更上一层楼。

    首先就从简单的非基础的基础开始(一定要有语言的基本功底,比如:变量、函数、运算符、类、对象等等)。

    我们先来做一个例子:交换两个数字的值。看一下代码:

       1:   public void Swap(int a, int b)
       2:          {
       3:              Console.WriteLine("交换前的两个值分别是:a={0},b={1}",a,b);
       4:              int temp;
       5:              temp = a;
       6:              a=b;
       7:              b = temp;
       8:              Console.WriteLine("交换后的两个值分别是:a={0},b={1}",a,b);
       9:          }

    这是典型的按照值类型的交换,在交换过程前加入有两个数字num1=1、num2=2,调用此函数在函数内部实现交换绝对是没有问题的,也可以实现交换的输出。但是外部的num1,num2真的实现了交换吗?我们来分析一下,如果我来调用Swap(num1,num2),两个实参传入方法,形参a、b接受参数,对应的a=1,b=2,在函数内部交换的值只是形参(实参的数值的一个复制,不会对实参产生影响),所以再出的交换对num1,num2不会产生影响。一句话,这就是按值传递!按值传递只能将数据带入构造函数,不能带出构造函数,因此num1,num2不会发生变化。

    那么怎样实现真正的交换数值呢?答曰:引用传递!按引用传递时将数值的地址传递过去,同时执行一个地址,一次修改一个,另一个也会发生变化!在C#中我们通常借用ref,out实现这类情况!

    例如代码:

       1:  static void Main(string[] args)
       2:          {
       3:              int num1 = 1;
       4:              int num2 = 2;
       5:              Console.WriteLine("a={0},b={1}",num1,num2);
       6:              Swap(ref num1,ref num2);
       7:              Console.WriteLine("a={0},b={1}", num1, num2);
       8:   
       9:          }
      10:          public static void Swap( ref int a,ref int b)
      11:          {
      12:              int temp;
      13:              temp = a;
      14:              a = b;
      15:              b = temp;
      16:          }
     
    这样就会交换成功!

    为什么会这样呢?ref的作用是什么呢?ref 关键字使参数按引用传递。 其效果是,当控制权传递回调用方法时,在方法中对参数的任何更改都将反映在该变量中。通俗的讲按引用传递时既可以将参数带入方法,亦可以将参数值带出方法。对同一个地址的数值修改肯定会影响变量的值,因此改变,交换成功!

    注意:

    请不要将“通过引用传递”概念与“引用类型”概念相混淆。这两个概念不相关;方法参数无论是值类型还是引用类型,都可通过 ref 进行修饰。 因此,通过引用传递值类型时没有值类型装箱。

    那么什么是Out呢?请看这个例子:

       1:  class Class1
       2:  {
       3:      static void Method(out int i)
       4:      {
       5:          i = 44;
       6:      }
       7:      static void Main()
       8:      {
       9:          int value;
      10:          Method(out value);
      11:          // value=44
      12:      }
      13:  }
    尽管作为 out 参数传递的变量不必在传递之前进行初始化,但被调用的方法需要在返回之前赋一个值。

    尽管 ref 和 out 关键字会导致不同的运行时行为,但在编译时并不会将它们视为方法签名的一部分。 因此,如果两个方法唯一的区别是:一个接受 ref 参数,另一个接受 out 参数,则无法重载这两个方法。

    传值传递引用的主要区别实质是对地址的使用,按引用传递是赋值一个副本,而按引用传递时则是对地址的传递,直接修改原始。

    那么对引用类型量传递时间会涉及此类问题吗?我认为是不会的,下面我们会通过一个例子来演示这个结论。首先我先说出这个结论:引用类型的变量传递是按引用传递的,直接对地址操作!(数组类型是引用类型),下面我们来操作一个数组:

       1:   static void FillArray(ref int[] arr)
       2:          {
       3:              if (arr==null)
       4:              {
       5:                  arr = new int[10];
       6:              }
       7:              arr[0] = 1111;
       8:              arr[2] = 2345;
       9:          }
      10:          static void Main(string[] args)
      11:          {
      12:              int[] arr = new int[10] { 1,2,3,4,5,6,7,8,9,0};
      13:              FillArray(ref arr);
      14:              string s = "";
      15:              foreach (var a in arr)
      16:              {
      17:                  s+= a+"\t";
      18:              }
      19:              Console.WriteLine(s);
      20:          }

    输出结果是已经修改过的数组:

    1111    2       2345    4       5       6       7       8       9       0

    下面我们直接不适用ref来传递数组:

       1:  //注意不适用ref关键字 
       2:  static void FillArray( int[] arr)
       3:          {
       4:              if (arr==null)
       5:              {
       6:                  arr = new int[10];
       7:              }
       8:              arr[0] = 1111;
       9:              arr[2] = 2345;
      10:          }
      11:          static void Main(string[] args)
      12:          {
      13:              int[] arr = new int[10] { 1,2,3,4,5,6,7,8,9,0};
      14:              FillArray( arr);
      15:              string s = "";
      16:              foreach (var a in arr)
      17:              {
      18:                  s+= a+"\t";
      19:              }
      20:              Console.WriteLine(s);
      21:          }
     
    得到的结果依旧是:

    1111       2       2345       4       5        6      7        8         9        0

    (【数组是按引用传递的,所以用不用ref是一样的..                         】)这样子理解是错误的,稍后会解释这是为什么。关于值类型,引用类型,按值传递,按引用传递是怎么运行的,有什么关系 后文给出明确的解释,在此记录作为学习记录。

  • 相关阅读:
    Win10版《芒果TV》全平台直播第89届奥斯卡颁奖典礼,特设第二演播室带来一手资讯
    Win10《芒果TV》商店版跻身Windows商店《热门免费应用》前12强
    Win10《芒果TV》商店版更新v3.2.6:修复后台任务故障,优化推送频次
    Win10《芒果TV》商店版更新v3.2.5:新增会员频道,修复多处细节问题,小年快乐
    Win10《芒果TV》商店版2016-2017春节大礼,每日前100名用户免费领取7天VIP
    Win10版《芒果TV》获评2016年度Windows Store最佳官方/休闲娱乐应用(LiveSino和微软信仰中心联合评选)
    [Cocos2d-x for WP8学习笔记] 一些基本概念,建立自己的启动界面
    [Cocos2d-x for WP8学习笔记] HelloWorld结构分析
    [Cocos2d-x for WP8学习笔记] HelloWorld
    WindowsPhone使用HtmlAgilityPack解析HTML
  • 原文地址:https://www.cnblogs.com/sunBolg/p/2477273.html
Copyright © 2011-2022 走看看