黑马程序员-console.writeline,不定长参数以及params

来源:互联网 发布:mac上其他怎么删除 编辑:程序博客网 时间:2024/05/19 02:29

------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------

console.writeline()有一个重载是这样的:

public static void WriteLine(string format, params object[] arg);

百度params,进一步得出答案:

arams 构造函数声明数组 而不知道数组长度 用的
在方法声明中的 params 关键字之后不允许任何其他参数,并且在方法声明中只允许一个 params 关键字。

形如:
using System;
public class MyClass 
{
    public static void UseParams(params object[] list) 
    {
        for (int i = 0 ; i < list.Length; i++)
        {
            Console.WriteLine(list[i]);
        }
        Console.WriteLine();
    }

params参数允许数组在运行时确定长度

也就是说wirteline函数这个重载把N个参数都放进一个数组中,不过数组的长度是多少,然后根据format中占位符的数量把数组中的参数读取出来

然而问题又来了,后面的数组中的数据类型是不同的,程序怎么知道要读取的变量在内存中有多长呢?

答案是显然的,函数把所有的变量都打包成了object类型,而object类型是所有类型的子类

再继续深挖下去,object类型是固定长度的吗?于是我们的新问题就变成了,object类型在底层的具体实现是什么样的?


笔者先不给出答案,笔者想到C语言中函数的一种写法:

void func(char *str,...);

这个...不是我故意省略了,而是真的可以写成"..."(必须是3个点)

这代表编译器不检查第一个参数后面参数的类型和个数,而读取参数的工作交给程序员来完成

具体读取的过程大概是这样的:

声明一个字符指针(因为C语言中字符指针的偏移量是1个字节)指向字符串str的末尾(也就是后面一个参数的开始)

按字符读取str串,比如这个串是“dcs”,读取到第一个字符d

这时进入一个switch循环中:

 ...

case d:

printf("%d",p);//读取一个整形变量那么长然后输出,假设我们这个函数的实现是输出不定长个变量

p+=sizeof(int);//p是刚才那个字符指针,偏移4个字节,指向下一个变量的开始

break;

...

然后读取第二个字符c,c表示读取一个char类型,指针偏移 加1个字节,指向第三个变量

第三个是s,表示读取一个字符串,指针一直加1直到遇见"\0"结束标记

如果前面串中还有字符,就依次类推。

这种读取方式基于一个假定的事实,所有的参数在内存中都是连续储存的,如果不连续,就无法确定偏移量是多少

我们再回到C#中来,思考一下object类型:

笔者推测出,object类型实际上封装了一个指针,和一个说明参数类型的字节(也可能是多个字节,但总之这个说明占用的长度是固定的)

指针的大小也是固定的4个字节,所以所有的object都有统一大小,而由其生成子类型的方式,其实是根据指针指向了内存中那个子类型变量的区域

那么你们还能提出更多问题吗,比如拆箱和装箱?留给你们去思考吧,嘿嘿

原创粉丝点击