zoukankan      html  css  js  c++  java
  • C#参数详解

    参数


    可选参数与命名参数

      设计方法时,我们可以为部分参数设置默认值,在方法调用时就可以不提供该参数,使用其默认值。此外,调用方法时可以通过指定参数名的方式来传递参数。话不多说,请看以下示例:

        static void Main(string[] args)
        {
            SomeMethod();   //X=0,Y=0,Z=0
            SomeMethod(y: 5, z: 10);  //X=0,Y=5,Z=10
            Console.ReadLine();
        }
    
        private static void SomeMethod(int x = 0, int y = 0, int z = 0)
        {
            Console.WriteLine($"X={x},Y={y},Z={z}");
        }
    

    上述SomeMethod方法,接受Int类型参数x、y、z,并设置默认值0。第1次调用时没有指定参数,C#编译器自动嵌入参数的默认值。第2次则为y和z参数显示指定了要传递的值。

    可选参数的使用规则

    • 有默认值的参数必须放在没有参数值的所有参数之后。
    • 默认值必须是编译时能确定的常量值(例如不能将参数的默认值设置为DateTime.Now)。
    • 不能重命名参数变量。
    • 更改参数的默认值具有潜在的危险性(调用该方法可能产生意料之外的结果)。
    • 如果参数使用ref或out关键字标识,就不能设置默认值。

    以传递引用的方式传递参数

      在方法中,参数是值类型还是引用类型,两种情况下的处理方式有着明显的不同。

        static void Main(string[] args)
        {
            int i = 0;
            GetVal(i);
            Console.WriteLine(i);   //0
    
            int[] arr = new int[] { 0 };
            GetVal(arr);
            Console.WriteLine(arr[0].ToString());     //10
            Console.ReadLine();
        }
    
        private static void GetVal(int p_Int)
        {
            p_Int = 10;
        }
    
        private static void GetVal(int[] p_Arr)
        {
            p_Arr[0] = 10;
        }
    

    对于值类型实例,传递给方法的是实例的一个副本,方法中对这个副本的操作不影响调用者中的实例;对于引用类型实例,传递给方法的是实例对象的引用(或者说指向对象的指针)。CLR允许以传引用而非传值的方式传递参数,在C#中,使用out或ref关键字实现此功能。

    out和ref关键字的区别

    使用ref关键字时,调用方法前必须初始化参数的值,被调用的方法可以对该值进行读取或写入;使用out关键字时,在调用方法之前可以不进行初始化,必须在方法中进行初始化

    如下,向GetVal传递未经初始化的参数str2时,无法通过编译。

        static void Main(string[] args)
        {
            string str = "before Porcess";
            GetVal(ref str);
            Console.WriteLine(str);
    
            string str2;
            GetVal(ref str2);   //Error:Use of unassigned local variable 'str2'
            Console.WriteLine(str2);
            Console.ReadLine();
        }
    
        private static void GetVal(ref string p_Str)
        {
            p_Str = "Processed";
        }
    

    修改上述GetVal方法,在方法内部不对参数进行初始化,依旧无法通过编译。

        //Error:The out parameter 'p_Str' must be assigned to before control leaves the current method
        private static void GetVal(out string p_Str)
        {
            string anotherStr = "Processed";
        }
    

    值类型使用out和ref

        static void Main(string[] args)
        {
            int i = 0;
            GetVal(ref i);
            Console.WriteLine(i);   //10
            Console.ReadLine();
        }
    
        private static void GetVal(ref int p_Int)
        {
            p_Int = 10;
        }
    

    上述代码,使用ref关键字,将变量i的地址传递给GetVal,p_Int是一个指针,指向Main栈帧中的i的值。在GetVal方法内部,p_Int指向的值被修改为10。

    引用类型使用out和ref

        static void Main(string[] args)
        {
            int[] arr = new int[] { 0 };
            GetVal(arr);
            //GetVal(ref arr);
            Console.WriteLine(arr[0].ToString());   //0
            Console.ReadLine();
        }
    
        private static void GetVal(int[] p_Arr)
        //private static void GetVal(ref int[] p_Arr)
        {
            p_Arr = new int[] { 0 };
            p_Arr[0] = 10;
        }
    

    这段代码输出的结果是0,和本节开头为方法传递数组的示例输出结果不太相同。差别仅为在方法中构造了一个新的对象,从输出结果可以看出,新对象的指针并没有返回给调用者。为了将新对象返回给调用者,可以使用out和ref关键字(注释掉的部分)。

    注意:以传递引用的方式传给方法变量时,参数类型必须与方法签名中声明的类型完全一致。

    可变数量参数

      方法有时需要获取可变数量的参数,使用params关键字,使方法能够接受可变数量的参数。

        static void Main(string[] args)
        {
            int i = Add(1, 2, 3, 4, 5, 6, 7, 8, 9);
            Console.WriteLine(i);
            Console.ReadLine();
        }
    
        private static int Add(params int[] p_Arr)
        {
            int sum = 0;
            for (int i = 0; i < p_Arr.Length; i++)
            {
                sum += p_Arr[i];
            }
            return sum;
        }
    

    使用params关键字时,编译器会向参数应用定制特性System.ParamArrayAttribute的一个实例。

    执行步骤:

    1. 当C#编译器检测到方法调用时,会首先检查所有具有指定名称、同时参数没有应用ParamArray特性的方法。
    2. 如果找到匹配的方法,就生成调用的代码。
    3. 如果没有找到,就接着检查应用了ParamArray特性的方法。
    4. 找到匹配的方法,编译器先生成代码构造一个数组,填充元素,再生成代码来调用所选的方法。
  • 相关阅读:
    常见排序算法及其C++实现
    Arc Engine二次开发——弹窗进行属性查询
    Python:Shapefile矢量转化为GeoJSON格式
    Python:GeoJson格式的多边形裁剪Tiff影像并计算栅格数值
    Java调用Python相关问题:指定python环境、传入参数、返回结果
    标准WPS框架下的空间信息处理服务部署方法
    AE开发—利用IQueryFilter接口进行属性查询
    Java调用Javascript、Python算法总结
    百度地图爬虫——获取某区域所有中学附近的网吧数据
    Python中使用面状矢量裁剪栅格影像,并依据Value值更改矢量属性
  • 原文地址:https://www.cnblogs.com/Answer-Geng/p/7517791.html
Copyright © 2011-2022 走看看