C#中参数的传递方式详解

值类型参数按值传递

    class Program
    {
        static void Main(string[] args)
        {
            int a = 10;
            Add(a);
            Console.WriteLine("传递之后的值为:" + a);
            Console.ReadKey();
        }

        private static void Add(int i)
        {
            Console.WriteLine("传递之前的值为:" + i);
            i = i + 10; 

        }
    }

结果:

可见,值类型参数在被方法调用的时候,是对本身实例的拷贝和操作,在方法调用前后参数值不变。

引用类型参数按值传递

当引用类型参数传递时,是对托管堆上对象实例内容的操作。
也就是引用类型按值传递,传递的是引用变量的指针,指向托管堆上的对象实例。

    class Program
    {
        static void Main(string[] args)
        {
            Student student = new Student();
            Add(student);
            Console.WriteLine("参数传递之后的值为:" +student._score);
            Console.ReadKey();
        }

        private static void Add(Student s)
        {
           Console.WriteLine("参数传递之前的值为:" + s._score);
            s._score = 90;
        }
    }

    public class Student
    {
        public int _score = 80;
    }

结果

可见,引用类型参数在被方法调用的时候,是针对变量的引用的操作,一旦引用对象内容发生改变,原来变量的值也随着改变。

按引用传递 ref和out

引用类型参数按值传递和按引用传递的不同之处:

  • 按值传递,传递的是参数本身的值,即引用指针。
  • 按引用传递,传递的是参数的地址,也就是实例指针。

另外,值类型也有按引用传递,这时候,传递的是值类型的地址。

   class Program
    {
        static void Main(string[] args)
        {
            int i = 100;
            string str = "one";
            ChangeByValue(ref  i);
            ChangeByRef(ref str);
            Console.WriteLine(i);
            Console.WriteLine(str);

            Console.ReadKey();
        }

        private static void ChangeByValue(ref int iValue)
        {
            iValue = 200;
        }

        private static void ChangeByRef(ref string sValue)
        {
            sValue = "One more";
        }
    }

可见,不管是值类型,还是引用类型,加入关键字ref作为参数,就意味着是对参数地址的操作,即托管堆上实例地址的改变。

另外:

  • 如果需要按引用传递,方法的定义和方法的调用,都要显式地使用ref和out。
  • 如果一个方法的参数除了ref和out关键字不同,还有其他参数不同,这才构成方法的2个重载。如果仅仅ref和out关键字不同,会报错"...不能仅在ref和out上有差别的重载方法"。

ref和out使用时的不同点:

out告诉编译器,参数会在方法内部初始化,而在方法之前不需要初始化。

int x;
Foo(out x);

ref告诉编译器,参数在方法之前必须初始化。

int y = 0;
Foo(ref y);

特殊引用类型string的传递

    class Program
    {
        static void Main(string[] args)
        {
            string str = "Old String";
            Console.WriteLine("传递之前的值为:" + str);
            ChangeStr(str);
            Console.WriteLine("传递之后的值为:"+str);
            Console.ReadKey();
        }

        private static void ChangeStr(string astr)
        {
            astr = "Change String";
        }
    }

结果:

可见,虽然string是引用类型,但按值传递的表现和值类型按值传递的表现一样。

总结

  • 引用类型按值传递,改变的是引用变量指向的托管堆上对象实例的内容。
  • 引用类型按引用传递,改变的是引用变量指向的托管堆上对象实例的地址。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

(0)

相关推荐

  • C#中的数组作为参数传递所引发的问题

    原则:尽可能控制对数据的修改,如果可以预测某个数据不会或不应该被改变,就要对其控制,而不要期望使用这个数据的调用者不会改变其值. 如果参数在使用过程中被意外修改,将会带来不可预知的结果,而且这种错误很难被检查到,所以我们在设计方法参数的时候,要充分考虑传递引用类型参数或者引用方式传递引用类型参数可能带来的后果. 如果一个数据在传递过程中不能被改变,就要在构建这个对象的时候就使其值(字段或属性)不被改变. 一.对于简单的参数的控制 1.值类型参数传递 这种情况因为传递的是参数的副本,不影响原始值,

  • C#使用Post调用接口并传递json参数

    目录 Post调用接口并传递json参数 Post请求参数(发送Json参数.发送普通参数) 1.发送Json格式的Post请求 2.带参数的Post请求 Post调用接口并传递json参数 public string Post(string Url, string jsonParas) { string strURL = Url; //创建一个HTTP请求 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strURL); /

  • c#线程间传递参数详解

    线程操作主要用到Thread类,他是定义在System.Threading.dll下.使用时需要添加这一个引用.该类提供给我们四个重载的构造函数(以下引自msdn). Thread (ParameterizedThreadStart)  初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托.  Thread (ThreadStart)  初始化 Thread 类的新实例. Thread (ParameterizedThreadStart, Int32)  初始化 Threa

  • C#多线程传递参数及任务用法示例

    本文实例讲述了C#多线程传递参数及任务用法.分享给大家供大家参考,具体如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleSample { class Program { static void Main(string[] args) { Console.WriteLine("这是主线程&

  • C#往线程里传递参数的方法小结

    传参方式有两种: 1.创建带参构造方法类 传参 2.利用Thread.start(8)直接传参,该方法会接收一个对象,并将该对象传递给线程,因此在线程中启动的方法 必须接收object类型的单个参数. Thread (ParameterizedThreadStart) 初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托. Thread (ThreadStart) 初始化 Thread 类的新实例. 由 .NET Compact Framework 支持. Thread (

  • C#传递参数到线程的方法汇总

    本文汇总整理了传递参数到线程的方法供大家参考,非常实用,具体内容如下: 首先我们要知道什么是线程,什么时候要用到线程,如何去使用线程,如何更好的利用线程来完成工作. 线程是程序可执行片段的最小单元,是组成运行时程序的基本单元,一个进程有至少一个线程组成.一般在并行处理等待事件的时候要用到线程,如等待网络响应,等待I/O通讯,后台事务处理等情况.使用线程其实很简单,在.net框架下面你首先要定义一个函数来完成一些工作,然后实例化一个线程对象Thread thrd = new Thread(new

  • 一道关于C#参数传递的面试题分析

    本文实例分析了一道关于C#参数传递的面试题.分享给大家供大家参考.具体如下: 1.定义一个类MPigeon,调用一个Swap交互函数,问最后实参的结果是什么 类定义: public class MPigeon { public string Name { get; set; } } 交换函数: public void Swap(object a,object b) { object temp=a; a=b; b=temp; } 测试代码: private void button2_Click(o

  • C#中的多线程多参数传递详解

    之前做了一个小的应用程序,用的是c#语言,涉及到了多线程的多参数传递,经过查找资料总结了一下解决方案! 第一种解决方案的原理是:将线程执行的方法和参数都封装到一个类里面.通过实例化该类,方法就可以调用属性来实现间接的类型安全地传递多个参数.看如下代码: 复制代码 代码如下: using System;using System.Threading; //ThreadWithState 类里包含了将要执行的任务以及执行任务的方法public class ThreadWithState {//要用到的

  • asp.net(C#)函数对象参数传递的问题

    复制代码 代码如下: class Program { static void Main(string[] args) { TestClass objA = new TestClass(); objA.Name = "I am ObjA"; Console.WriteLine(String.Format("In Main:{0}", objA.Name)); TestFun(objA); Console.WriteLine(String.Format("In

  • C# 使用匿名函数解决EventHandler参数传递的难题

    首先,动态生成PictureBox,很简单, PictureBox box = new PictureBox() ; box.ImageLocation = imageRoad ; 其次,给PictureBox添加右键菜单,也不难, ContextMenu menu = new ContextMenu(); box.ContextMenu = menu ; 然后,要给右键菜单增加"删除"项,并实现删除图片事件.这个,比较麻烦. MenuItem item = new MenuItem(

  • C#实现向函数传递不定参数的方法

    本文实例讲述了C#实现向函数传递不定参数的方法.分享给大家供大家参考.具体实现方法如下: using System; class Min{ public int MinVla(params int [] nums){ int m; if (nums.Length == 0){ Console.WriteLine("Error: no arguments."); return 0; } m = nums[0]; foreach ( int val in nums){ if ( val &

随机推荐