zoukankan      html  css  js  c++  java
  • CLR via C#(10)-参数

    一、 命名参数、可选参数

    命名参数和可选参数是在Visual C#2010中引入的新特性。 笨地儿我个瓜不兮兮的,今天才知道高脚杯

    • 可选参数:定义方法时为参数设置默认值,调用该方法时可以省略为某些形参指定实参。
    • 命名参数:调用方法时,通过指定参数名称的方式为特定形参指定实参。指定时是根据名称将形参和实参关联,而不是与参数在列表中的位置关联。

    例如:

    class Program
        {
            static void Main(string[] args)
            {
                //可选参数
                Employee.DisplayInfo(24, "程序员");         //相当于 Employee.DisplayInfo(24, "程序员", 0, "未知",default(datetime));
                Employee.DisplayInfo(25, "英语相关", 9500); //相当于 Employee.DisplayInfo(25, "英语相关", 9500,"未知",default(datetime));
                //命名参数
                //相当于Employee.DisplayInfo(30, "高级软件工程师", 20000, "Yathur",DateTime.Now);
                Employee.DisplayInfo(30, Job: "高级软件工程师", Salary: 20000, Name: "Yathur", dt: DateTime.Now);
                Employee.DisplayInfo(Age: 25, Job: "教师");
                Console.Read();
            }
        }
        public class Employee
        {
            public static void DisplayInfo(int Age, string Job, int Salary = default(int), string Name = "未知", DateTime dt = default(DateTime))
            {
                Console.WriteLine("姓名:" + Name + ",   年龄:" + Age + ",   职位:" + Job + ",   月薪" + Salary + "   " + dt);
            }
        }运行结果:

    image

    在智能感知中,可选参数为方括号标识。

    image

    有了命名参数,调用时可以方便地按照形参名称进行,我们不需要记住或查找形参在所调用方法的形参列表中的顺序。 有了可选参数,当面对包含大量参数的方法时,如果含有默认值,我们可以只给有意义的参数指定实参,用起来方便了很多。

    使用规则:
    • 未设置默认值的参数也可以按名称传递。

    Employee.DisplayInfo( Age:25,Job:"教师");

    • 命名参数可以调换顺序,但是得保证有默认值的参数必须放在无默认值的参数之后,否则会产生编译错误。

             image

    注意:如果参数中存在数组参数,这个规则不成立。因为数组参数没有默认值,也要放到参数列表的最后。

    • 默认值必须是编译时就能确定的值。例如基元类型、枚举类型、能设为Null的引用类型等。经常将默认值设置为相应的零值,可以使用关键字default、new来实现。
    • 含有ref或Out关键字的参数不能设置默认值,会产生编译错误。因为这些参数不好设置有意义的默认值

    二、 引用方式传参—Out, Ref

    CLR假定方法的参数是以传值方式进行的,但它允许以传引用的方式传递参数。C#通过Out和ref关键字可以传递指向实例的一个指针,而不是参数本身的值。

    Out和Ref的使用区别:

    • Out: 在调用之前不必初始化参数值;   被调用的方法内部不能读取参数值;        返回之前必须为该参数赋值。
    • Ref:  调用之前必须初始化参数值;      被调用方法可以读取或者写入参数的值;  返回之前可以不为该参数赋值(不考虑程序实际意义)。
    1. 值类型使用Out和Ref

    image

    运行结果:

    image

    相应的IL元数据:

    image

    2. 引用类型使用out和ref

    当调用方法时,如果形参类型为实参类型的基类,一般会发生隐式转换。例如:

    public static void Swap(object a, object b)
           {
               object t = a;
               a = b;
               b = t;
           }

              string a = "AAA", b = "BBB";
              Swap(a, b);
              Console.WriteLine("a=" + a + " b=" + b);

         image

    但是运行结果并非我们所愿,因为方法默认是以传值方式传递参数的,调用后原来的值是不会改变的。

    当以传引用的方式向方法传递参数时,必须保证变量类型与方法签名中类型一致,而不能自动进行隐式转换,否则会产生编译错误。例如:

    public static void Swap(ref object a, ref object b)
          {
              object t = a;
              a = b;
              b = t;
          }

        image

    为了实现想要的效果,我们可以采用泛型

    public static void Swap<T>(ref T a, ref T b)
           {
               T t = a;
               a = b;
               b = t;
           }

    static void Main(string[] args)

    {

    string a = "AAA", b = "BBB";

    Swap(ref a, ref b);

    Console.WriteLine("a=" + a + " b=" + b);

    Console.Read();

    }

    image

    3. 重载

    在C#中,可以使用Out或者ref关键字进行方法重载,例如下面的例子是合法的:

    image

    image

    但是如果两个方法名称和参数相同,仅通过out和ref关键字是不能算作重载的。

    image

    image

    、 可变数量参数传递—Params

    某些时候,我们希望方法参数的个数是可变的,Params帮我们实现了这个想法。

    实例

    image

    image

    假如不使用Params关键字,我们需要使用第①种调用方式。当添加Params关键字后,我们可以采用②③,调用方式看上去更加直观了。实现了传递可变数量参数的效果。

    注意事项:
    • Params关键字参数只能放在参数列表的最后,如果调换上面例子中两个参数位置,会产生编译错误。

              image

      • Params关键字只能标识任意类型的一个一维数组。
      • Params参数允许为Null值或者长度为0的数组。例如上面例子中的④⑤。
      • Params方式其实会造成一些性能损失,例如在堆上为数组分配内存、数组初始化等,所以尽量不要过多使用变长参数。

      文章出处:跟小静读CLR via C#

  • 相关阅读:
    codeforces 765 F Souvenirs 线段树+set
    codeforces 768 E 变形NIM博弈/手写sg函数
    BZOJ 1001 狼抓兔子(网络流)
    BZOJ 2957 楼房重建 (分块)
    CodeForces
    CodeForces
    HYSBZ
    SPOJ
    Codeforces-963 D Frequency of String
    中石油2019寒假集训第一场(新生场)(补题)
  • 原文地址:https://www.cnblogs.com/fireshadow23/p/3642934.html
Copyright © 2011-2022 走看看