• C#系列文章之参数


    解决的主要问题:

    1. 如何可选地制定参数
    2. 按名称指定参数
    3. 按引用传递参数
    4. 如何定义方法来接受可变数量的参数

    文章的主要内容:

    • 可选参数和命名参数
    • 隐式类型的局部变量
    • 以传引用的方式向方法传递参数
    • 向方法传递可变数量的参数
    • 参数和返回类型的设计规范
    • 常量性

    1.1可选参数和命名参数

    在方法中为部分参数指定默认值的规则和原则:

    • 可为方法,构造器方法和有参属性(C#索引器)的参数,委托定义一部分的参数指定默认值。并且默认值必须是编译时能确定的常量值,可以是基元类型,枚举类型以技能设为null的任何引用类型。可以使用default和new来设置默认值
    • 不要重命名参数变量(否则调用者在以传参数名的方式传递实参时要修改代码)。如果方法被模块的外部进行调用,不要随意更改默认值,比如下面的例子:                            
      //不要这样做
      private static string MakePath(string filename="Untitled")
      {
          return string.Format(@"C:{0}.txt",filename);
      }
      //而要这样做
      private static string MakePath(string filename=null)
      {
          return string.Format(@"C:{0}.txt",filename??"Untitled");
      }
    • 如果参数用ref或out关键字进行标识,则不能设置默认值,因为没有办法为这些参数传递有意义的默认值。

    调用方法时,传参数时规则和原则:

    • 命名参数只能出现在实参列表的尾部
    • 所有必须的实参必须都传递
    • 如果参数要求ref/out,为了以传递参数名的方式传递实参,要使用下面语法:
    //方法的声明
    private static void M(ref int x){.......}
    
    //方法的调用
    int a = 5;
    M(x:ref a);

     此外不能用var声明方法的参数类型,不要混淆dynamic和var。用var声明局部变量只是一种简化的语法,他要求编译器根据表达式推断出具体数据类型,其只能声明方法内部的局部变量,而dynamic关键字适用于局部变量,字段和参数。另外,必须显示初始化用var声明的变量。

    1.2以传引用的方式向方法传递参数(out ref)

         CLR默认所有方法参数都传值,对于引用类型,对象的指针被传给方法,这个指针也是当做值来传递的,意味着方法能修改对象。对于值类型,由于是在栈上,传给方法是一个副本,调用者中的实例不受影响。

         CLR不区分out和ref,无论用哪个都会生成相同的IL代码。元数据除了有一个bit用于说明是out还是ref外,剩下几乎一致。用out标记表明调用者在调用方法之前不指望你已初始化好了对象,被调用的方法不能读取参数的值,要求返回前必须向这个值写入。用ref标记,调用者就必须先初始化参数的值。为较大的值类型使用out,可提升代码执行效率,因为它避免了在进行方法调用时复制值类型实例的字段。

         CLR允许根据使用的是out 还是ref参数对方法进行重载,例如:

         

    //如下两个方法可以实现重载,
    //但是如果只有out和ref区别,则不合法,
    //因为两个签名的元数据形式相同
    public class Point
    {
        void Add(Point p){.....};
        void Add(ref Point p){.....};
    }

    1.3 向方法传递可变数量的参数

       使用如下声明,接受可变数量的参数

      

    int Add(params int[] values)
    {
       int sum =0;
       if(values!=null)
       {
          for(int x = 0; x<values.length;x++){.....}
        }
       return sum
    }

    调用时可以是Add(new int[]{1,2,3...});也可以是Add(1,2,3...);

            编译器在检测到方法调用时,会检查所有具有指定名称同时参数没有应用ParamArray特性的方法。找到就生成调用它所需的代码,否则就检查应用ParamArray特性的方法,此时编译器生成代码构造一个数组,填充元素,再生成代码来调用所选的方法。

            只有方法最后一个参数才可以用Params关键字标记,也只能标识一组数组(任意类型),可传递null或不传值;

            调用参数数量可变的方法对性能有所影响(除非显式传递null)。毕竟数组对象必须在堆上分配,数组元素必须初始化,而且数组内存最终需要垃圾回收。为此可以定义几个没有使用params关键字的重载版本。

    1.4 参数和返回类型的设计规范

            声明方法参数类型应尽量指定最弱类型,宁愿要接口也不要基类。比如处理一组数据项,最好用IEnumerable<T>,而不要用强数据类型List<T>或强接口类型ICollection<T>或IList<T>。原因是要尽可能使接受的参数范围广,更灵活。相反一般将方法返回类型声明为最强类型(防止受限于特定类型)。总之确保调用者调用方法有尽量大的灵活性,使方法适用范围更大。

             有时在不影响调用者前提下修改方法内部实现。如果方法返回List<string>,可能会在未来某个时候修改内部方法实现返回string[]。若想保持一定的灵活性,可以选择较弱的返回类型。比如IList<string>不建议使用最弱的IEnumerable<string>,也不使用较强的IConllction<string>

  • 相关阅读:
    安卓模拟器BlueStacks 安装使用教程(图解)
    照相机滤镜使用,优化解码和滤镜导致的预览卡屏现象
    移动语音引擎相关开发笔记
    Linux下查看硬件信息的方法
    linux下彻底卸载mysql 图解教程
    linux下yum安装及配置
    mybatis中的resultMap
    项目管理模式之如何去除SVN标记
    myeclipse中的classpath
    Spring的AOP配置
  • 原文地址:https://www.cnblogs.com/mjys-gh/p/6459477.html
Copyright © 2020-2023  润新知