关于 C# 方法参数的理解

1.值参数引用参数

  在不考虑 ref 和 out 修饰的情况下,传递值类型的参数就是值参数,参数在方法中的修改不会保留;

  传递引用类型的参数就是引用参数,参数在方法中的修改都会保留(在不为该引用参数重新赋值实例化的前提下,参数在方法中的修改才会保留,否则一样不保留)。

public ActionResult Index()
{
    int i = 0;
    TestMethod1(i);
    // 此时这里的i还是0,因为int是值类型。

    TestClass tc = new TestClass();
    tc.i = 0;
    TestMethod2(tc);
    // 此时这里的tc.i变为1,因为TestClass是引用类型。

    tc.i = 0;
    TestMethod3(tc);
    // 此时这里的tc.i仍为0,因为TestClass虽然是引用类型,但在方法中已经重新实例化对象,跟之前的tc对象已经不是同一个了。

    return View();
}

private void TestMethod1(int i)
{
    i = 1;
}

private void TestMethod2(TestClass tc)
{
    tc.i = 1;
}

private void TestMethod3(TestClass tc)
{
    tc = new TestClass();
    tc.i = 1;
}

class TestClass
{
    public int i { set; get; }
}

按值传递参数相当于就是把参数复制了一份传到方法里面去,而复制品怎么改变都不会影响样品;同样,按引用传递参数后,在方法里重新实例化也相当于复制。

  

  那么是不是传递值类型参数就不能改变方法外的变量了呢,不是,我们把值参数变成引用参数就可以了。只需要在值类型参数前面加上ref(引用参数)修饰,那么本该是值参数就会变成引用参数(参数本身还是值类型):

public ActionResult Index()
{
    int i = 0;
    TestMethod4(ref i);  //参数必须是变量,传参前要赋值。
    // 此时这里的i变为1了,加了ref关键字。

    return View();
}

private void TestMethod4(ref int i)
{
    i = 1;
}

 2.out(输出参数)

  必须在声明和调用中都使用 out 修饰符(ref 也是同样)。

public ActionResult Index()
{
    string msg1, msg2;
    bool whether = TestMethod5(out msg1, out msg2);
    // 得到msg1为"张三执行",msg2为"成功"

    return View();
}

private bool TestMethod5(out string msg1, out string msg2)
{
    msg1 = "张三执行";
    msg2 = "成功";   //在方法中必须要初始化赋值
    return true;
}

  out(输出参数)适合用在需要 retrun 多个返回值的地方;而 ref(引用参数)则用在需要被调用的方法修改调用者的引用的时候。

  out 和 ref 的区别:https://www.cnblogs.com/Allofus/p/14774691.html

 3.params(数组参数)

  • 在一个参数列表中只能有一个参数数组
  • 如果有,它必须是列表中的最后一个
  • 不允许将 params 修饰符与 ref 和 out 修饰符组合起来使用
  • 数组是一个引用类型,因此它的所有数据项都保存在堆中
public ActionResult Index()
{
    int[] arr = { 1, 2, 3, 4, 5, 6 };
    int[] b = TestMethod6(arr);

    return View();
}

private static int[] TestMethod6(params int[] arr)
{
    return arr;
}

4.可选参数

   可选参数是 .NET4 中新添加的功能,应用可选参数的方法在被调用的时可以选择性的添加需要的参数,而不需要的参数由参数默认值取代。

public ActionResult Index()
{
    int i = 0;
    string s1 = TestMethod7(i); //结果为"0是失败"
    string s2 = TestMethod7(i, "是成功"); //结果为"0是成功"

    return View();
}

private string TestMethod7(int i, string str = "是失败")
{
    return i + str;
}

5.命名参数

   命名参数是把参数附上参数名称,这样在调用方法的时候不必按照原来的参数顺序填写参数,只需要对应好参数的名称也能完成方法。

public ActionResult Index()
{
    string s = TestMethod8(str: "是成功", i: 0);    //结果为"0是成功"

    return View();
}

private string TestMethod8(int i, string str)
{
    return i + str;
}

命名参数如果只是改变参数的顺序,这样的意义并不大,我们没有必要为了改变顺序而去用命名参数,他与可选参数结合才能显示出他真正的意义。

public ActionResult Index()
{
    int i= 0;
    string s = TestMethod9(i, str2: "失败");  //结果是"0张三执行失败"

    return View();
}

private string TestMethod9(int i, string str1 = "张三执行", string str2 = "成功")
{
    return i + str1 + str2;
}

参考:https://zhidao.baidu.com/question/2011292093902737868.html

     https://www.cnblogs.com/weiming/archive/2011/12/28/2304937.html

原文地址:https://www.cnblogs.com/Allofus/p/10244096.html