• c#进阶params可变个数的参数


    目录

    1 简单使用

    2 可变个数的参数params 的原理

    3 性能分析

    4 较佳实践建议


      系列索引

    C#功能派的进阶2--类型的那些事


    1简单使用 

    static Int32 Add(params Int32[] values) { 
    // NOTE: it is possible to pass the 'values' 
    // array to other methods if you want to. 
    Int32 sum = 0
    if (values != null) { 
    for (Int32 x = 0; x < values.Length; x++
    sum 
    += values[x]; 

    return sum; 
    }

     明显他可以这样使用 

    public static void Main() { 
    // Displays "15" 
    Console.WriteLine(Add(new Int32[] { 12345 } )); 
    }

     但是这样有点丑,也许这样会漂亮点。params的特性

    public static void Main() { 
    // Displays "15" 
    Console.WriteLine(Add(12345)); 
    }

          但是哦呼,他真的可以运行。这是params参数的特权,去除params之后就会报错,因为他就变成了3个参数的函数了。是为了消除二义性,将不能再定义不带params 的函数。

    2可变个数的参数params 的原理

    在想params是如何实现的时候,我猜测params是编译器的语法糖在IL中不存在。打开reflactor来尝试验证

    public static void Main() { 
                DisplayTypes(
    134); 
                DisplayTypes(
    new Object[] { 134 }); 
                Console.Read();
            }
    private static void DisplayTypes(params Object[] objects) { 
               
    if (objects != null) { 
                   
    foreach (Object o in objects) 
                       Console.WriteLine(o.GetType()); 
               } 
           }

     对应的Main方法

    public static void Main()
    {
        
    object[] CS$0$0000;
        DisplayTypes(
    new object[] { (int1, (int3, (int4 });
        DisplayTypes(
    new object[] { (int1, (int3, (int4 });
        Console.Read();
        
    return;
    }

    果然不出所料。  

    另外补充来自你必须知道的.NET中的分析
    param关键字的实质是:param是定制特性ParamArrayAttribute的缩写(关于定制特性的详细论述请参见第三回:历史纠葛:特性和属性),该特性用于指示编译器的执行过程大概可以简化为:编译器检查到方法调用时,首先调用不包含ParamArrayAttribute特性的方法,如果存在这种方法就施行调用,如果不存在才调用包含ParamArrayAttribute特性的方法,同时应用方法中的元素来填充一个数组,同时将该数组作为参数传入调用的方法体。总之就是param就是提示编译器实现对参数进行数组封装,将可变数目的控制由编译器来完成,                                                  实质是: void XXXX(  [ParamArrayAttribute] int[] ages){...}

    3性能分析

    其实质其实构造一个 array 在编译时确定其长度来 承载可变个数的参数.但性能上并不划算:因为需要额外构造一个array。

    1在堆上分配内存

    2初始化其元素

    3最后还得被回收。

    所以出于性能更好的做法是重载。我们可以看String 中Concat的做法。 

    public sealed class String : Object, ... { 
    public static string Concat(object arg0); 
    public static string Concat(object arg0, object arg1); 
    public static string Concat(object arg0, object arg1, object arg2); 
    public static string Concat(params object[] args); 
    public static string Concat(string str0, string str1); 
    public static string Concat(string str0, string str1, string str2); 
    public static string Concat(string str0, string str1, string str2, string str3); 
    public static string Concat(params string[] values); 
    }

    4参数和返回值编写的较好实践:

    1参数和返回值尽量使用接口和基类

    显而易见,可以适用被更多种(派生)类型。

    2常量性(const-ness)的对象和参数

    类的常量性其实是自欺欺人,如前所述(我之前的一篇文章)我们虽然不能改变类的地址,但可以改变地址的值。这样的话C++等实现的常量性类,是在自欺欺人吗?其实我们可以在设计类的时候就不让他改变就得了?(private set),他也有很多不好的地方如 使得执行的时候需要检查是否是常量(不可改变)而降低性能。

  • 相关阅读:
    OpenCV-C++ 图像上采样和降采样
    OpenCV-C++ 图像形态学操作应用-提取水平与垂直线
    OpenCV-C++ 图像形态学操作
    OpenCV-C++ 图像滤波(二)-中值滤波-双边滤波
    OpenCV-C++ 图像滤波(一)-均值滤波-高斯滤波
    OpenCV-C++ 绘制基本形状与编写文字
    OpenCV-C++ 调整图像亮度和对比度
    OpenCV-C++ 图像混合
    Mysql新建表,插入中文时报错“Incorrect string value: 'xE4xBDxA0xE5xA5xBD' for column”问题
    springcloud11 spring cloud config
  • 原文地址:https://www.cnblogs.com/facingwaller/p/advance_in_csharp_about_params.html
Copyright © 2020-2023  润新知