c#参数传递几点小结

在C#中,方法的参数传递有四种类型: 传值(by value), 传址(by reference), 输出参数(by output), 数组参数(by array)。传值参数无需额外的修饰符,传址参数需要修饰符ref,输出参数需要修饰符out,数组参数需要修饰符params。传值参数在方法调用过程中如果改变了参数的值,那么传入方法的参数在方法调用完成以后并不因此而改变,而是保留原来传入时的值。传址参数恰恰相反,如果方法调用过程改变了参数的值,那么传入方法的参数在调用完成以后也随之改变。实际上从名称上我们可以清楚地看出两者的含义—— 传值参数传递的是调用参数的一份拷贝,而传址参数传递的是调用参数的内存地址,该参数在方法内外指向的是同一个存储位置
下面总结几种在项目中常用的参数传递:
1、常规值类型参数传递(如:整型参数传递)
Code
using System;

class Program
{
    
/// <summary>
    
/// 无引用参数
    
/// </summary>
    
/// <param name="m"></param>
    
/// <param name="n"></param>
    static void ParamTest(int m, int n)
    {
        m 
= 1;
        n 
= 2;
        Console.WriteLine(
"now,m={0},n={1}", m, n);
    }

    
/// <summary>
    
/// out参数
    
/// </summary>
    
/// <param name="m"></param>
    
/// <param name="n"></param>
    static void OutTest(out int m, out int n)
    {
        
//离开这个函数前,必须对m和n赋值,否则会报错。 
        
//n = m; 
        
//上面这行会报错,因为使用了out后,m和n都清空了,需要重新赋值,即使调用函数前赋过值也不行 
        m = 1;
        n 
= 2;
    }
    
    
/// <summary>
    
/// ref参数
    
/// </summary>
    
/// <param name="m"></param>
    
/// <param name="n"></param>
    static void RefTest(ref int m, ref int n)
    {
        m 
= 1;
        n 
= m;
    }

    
public static void Main()
    {
        
//值类型传递参数
        int i = 22, j = 33;
        ParamTest(i, j);
        Console.WriteLine(
"still,i={0};j={1}", i, j);

        
//out test
        int x, y;
        
//out使用前,变量可以不赋值
        OutTest(out x, out y);
        Console.WriteLine(
"here comes the out parameter:");
        Console.WriteLine(
"x={0};y={1}", x, y);
        
int xx = 11, yy = 22;
        OutTest(
out xx, out yy);

        Console.WriteLine(
"here comes the out parameter:");
        Console.WriteLine(
"xx={0};yy={1}", xx, yy);

        
//ref test
        int a, b;
        
//RefTest(ref a, ref b); 
        
//上面这行会出错,ref使用前,变量必须赋值

        
int aa = 10, bb = 100;
        RefTest(
ref aa, ref bb);
        Console.WriteLine(
"here comes the ref parameter:");
        Console.WriteLine(
"aa={0};bb={1}", aa, bb);
    }
}
2、结构参数传递
Code
using System;

public struct Student
{
    
public string name;
    
public Student(string name)
    {
        
this.name = name;
    }
}

class Program
{
   
    
/// <summary>
    
/// 无引用参数
    
/// </summary>
    
/// <param name="stu"></param>
    static void ParamTest(Student stu)
    {
        stu.name 
= "jeffery zhao";
        Console.WriteLine(
"now,the student's name is {0}",stu.name);
    }

    
/// <summary>
    
/// out参数
    
/// </summary>
    
/// <param name="m"></param>
    
/// <param name="n"></param>
    static void OutTest(out Student stu)
    {
        stu.name 
= "jeffery zhao";
    }
    
    
/// <summary>
    
/// ref参数
    
/// </summary>
    
/// <param name="m"></param>
    
/// <param name="n"></param>
    static void RefTest(ref Student stu)
    {
        stu.name 
= "jeffery zhao";
    }

    
public static void Main()
    {
        
//结构类型传递参数
        Student stu = new Student("jeff wong");
        ParamTest(stu);
        Console.WriteLine(
"still,student's name:{0}", stu.name);

        
//out test
        Student outStu;
        
//out使用前,变量可以不赋值
        OutTest(out outStu);
        Console.WriteLine(
"here comes the out parameter:");
        Console.WriteLine(
"student's name:{0}", outStu.name);

        Student outStu1 
= new Student("jeff wong");
        OutTest(
out outStu1);
        Console.WriteLine(
"here comes the out parameter:");
        Console.WriteLine(
"student's name:{0}", outStu1.name);

        
//ref test
        
//Student refStu;
        
//RefTest(ref refStu); 
        
//上面这行会出错,ref使用前,变量必须赋值

        Student refStu1 
= new Student("jeff wong");
        RefTest(
ref refStu1);
        Console.WriteLine(
"here comes the ref parameter:");
        Console.WriteLine(
"student's name:{0}", refStu1.name);
    }
}
3、普通引用类型参数传递
Code
using System;

public class Student
{
    
public string name;
    
public Student(string name)
    {
        
this.name = name;
    }
}

class Program
{
     static void ParamTest(Student stu)
    {
        Console.WriteLine(
"before modified,the student's name is {0}", stu.name);
        stu.name 
= "jeffery zhao";
        Console.WriteLine(
"now,the student's name is {0}",stu.name);
    }

    
/// <summary>
    
/// out参数
    
/// </summary>
    
/// <param name="m"></param>
    
/// <param name="n"></param>
    static void OutTest(out Student stu)
    {
        stu 
= new Student(""); //必须初始化,否则编译错误
        stu.name = "jeffery zhao";
    }
    
    
/// <summary>
    
/// ref参数
    
/// </summary>
    
/// <param name="m"></param>
    
/// <param name="n"></param>
    static void RefTest(ref Student stu)
    {
        stu.name 
= "jeffery zhao";
    }

    
public static void Main()
    {
        
//引用类型传递参数
        Student stu = new Student("jeff wong");
        ParamTest(stu);
        Console.WriteLine(
"still,student's name:{0}", stu.name);

        
//out test
        Student outStu = new Student("jeff wong");
        
//out使用前,变量可以不赋值
        OutTest(out outStu);
        Console.WriteLine(
"here comes the out parameter:");
        Console.WriteLine(
"student's name:{0}", outStu.name);

        
//ref test
        
//Student refStu;
        
//RefTest(ref refStu); 
        
//上面这行会出错,ref使用前,变量必须赋值

        Student refStu1 
= new Student("jeff wong");
        RefTest(
ref refStu1);
        Console.WriteLine(
"here comes the ref parameter:");
        Console.WriteLine(
"student's name:{0}", refStu1.name);
    }
}
4、 string类型参数传递(****)
Code
using System;

class Program
{
    
/// <summary>
    
/// 无引用参数
    
/// </summary>
    
/// <param name="m"></param>
    
/// <param name="n"></param>
    static void ParamTest(string m, string n)
    {
        m 
= "1";
        n 
= "2";
        Console.WriteLine(
"now,m={0},n={1}", m, n);
    }

    
/// <summary>
    
/// out参数
    
/// </summary>
    
/// <param name="m"></param>
    
/// <param name="n"></param>
    static void OutTest(out string m, out string n)
    {
        
//离开这个函数前,必须对m和n赋值,否则会报错。 
        
//n = m; 
        
//上面这行会报错,因为使用了out后,m和n都清空了,需要重新赋值,即使调用函数前赋过值也不行 
        m = "1";
        n 
= "2";
    }
    
    
/// <summary>
    
/// ref参数
    
/// </summary>
    
/// <param name="m"></param>
    
/// <param name="n"></param>
    static void RefTest(ref string m, ref string n)
    {
        m 
= "1";
        n 
= m;
    }

    
public static void Main()
    {
        
//string类型传递参数
        string i = "22", j = "33";
        ParamTest(i, j);
        Console.WriteLine(
"still,i={0};j={1}", i, j);

        
//out test
        string x, y;
        
//out使用前,变量可以不赋值
        OutTest(out x, out y);
        Console.WriteLine(
"here comes the out parameter:");
        Console.WriteLine(
"x={0};y={1}", x, y);
        
string xx = "11", yy = "22";
        OutTest(
out xx, out yy);

        Console.WriteLine(
"here comes the out parameter:");
        Console.WriteLine(
"xx={0};yy={1}", xx, yy);

        
//ref test
        string a, b;
        
//RefTest(ref a, ref b); 
        
//上面这行会出错,ref使用前,变量必须赋值

        
string aa = "10", bb = "100";
        RefTest(
ref aa, ref bb);
        Console.WriteLine(
"here comes the ref parameter:");
        Console.WriteLine(
"aa={0};bb={1}", aa, bb);
    }
}
通过上面的代码,我们发现string类型参数传递返回的结果和常规值类型参数传递(如:整型参数传递)返回的结果一致,这里把string类型单独拿出来,是为了区别对待string这种特殊类型。本质上string是引用类型,但是在实际计算和处理的时候,它处处透漏出值类型的特征。关于string类型,网上有无数精彩的文章介绍,这里不再多说。
5、数组参数
params 关键字可以指定在参数数目可变处采用参数的方法参数。 在方法声明中的 params 关键字之后不允许任何其他参数,并且在方法声明中只允许一个 params 关键字。
Code
using System;

class Program
{
    
/// <summary>
    
/// params关键字可以指定在参数数目可变处采用参数的方法参数。 在方法声明中的params关键字之后
    
/// 不允许任何其他参数,并且在方法声明中只允许一个params关键字。 
    
/// </summary>
    
/// <param name="intArr"></param>
    public static void ParamsTest(params int[] intArr)
    {
        
for (int i = 0; i < intArr.Length; i++)
            Console.WriteLine(intArr[i]);
    }

    
public static void Main()
    {
        Console.WriteLine(
"here comes the parameters:");
        
int[] intArr=new int[]{1,2,3};
        ParamsTest(intArr);

        Console.WriteLine(
"---------------------------");
        
int[] intsArr = new int[20];
        
for (int i = 0; i < intsArr.Length; i++)
        {
            intsArr[i] 
= i;
        }
        ParamsTest(intsArr);

    }
}

6、最后,总结一下:

在C# 中,既可以通过值也可以通过引用传递参数。通过引用传递参数允许函数成员更改参数的值,并保持该更改。若要通过引用传递参数, 可使用ref或out关键字。ref和out这两个关键字都能够提供相似的功效,其作用也很像C中的指针变量。它们的区别是:
传递参数中,关键字ref和out的区别:
(1)、使用ref型参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化。
(2)、使用ref和out时,在方法的参数和执行方法时,都要加Ref或Out关键字,以满足匹配。
(3)、out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。

你可能感兴趣的:(c#参数传递几点小结)