为什么params表现得像这样?

Cha*_*ion 23 c#

产量

1

2

空值

2

码

class Program
{        
    static void Main(String[] args)
    {
        String s = null;
        PrintLength(s);
        PrintLength(s, s);
        PrintLength(null);
        PrintLength(null, null);    
        Console.ReadKey();
    }

    private static void PrintLength(params String[] items)
    {
        Console.WriteLine(items == null ? "null" : items.Length.ToString());
    }    
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 29

这是一个经常被问到的问题.有关详细信息,请参阅规范的7.4.1和7.4.3.1.

简而言之:具有params数组的方法适用于其"正常形式"或其"扩展形式".也就是说,你可以说

PrintLength(new string[] {"hello"}); // normal form
PrintLength("hello"); // expanded form, translated into normal form by compiler.
Run Code Online (Sandbox Code Playgroud)

当给出适用于两种形式的调用时,编译器总是在扩展形式上选择普通形式.

假设我们每次都适用时选择扩展形式.假设你有

void M(params object[] x) {}
Run Code Online (Sandbox Code Playgroud)

如果我们总是选择扩展形式,你会如何实际将空数组传递给这个东西?那是不可能的!

假设你说

M(new object[] { "hello" });
Run Code Online (Sandbox Code Playgroud)

我们总是选择扩展形式.这会是什么?好吧,一个对象数组是一个对象,所以这将选择扩展形式 - 它将创建另一个数组,将这个东西包装在数组中,并传递它!

扩展形式超过正常形式的选择导致疯狂的结果.总是在扩展形式上选择正常形式是更明智的做法.


mar*_*c_s 5

我按照设计工作,我会说:

PrintLength(一个或多个);

你正在传递一个字符串,它是空-你的方法里面,items会不会为空-这是一个元素的数组-字符串类型-价值null

PrintLength(s,s);

同样的故事在这里 - 你传递了两个元素,所以items在你的方法中将是一个由两个字符串组成的数组 - 这两个字符串本身都是null,但数组不是

PrintLength(NULL);

这显然被解释为单个NULL值,因此items为null.你没有传入一个数组,也没有传入一个string类型的元素 - 你只是传入一个空值本身.

PrintLength(null,null);

这又是一个由两个元素组成的数组,两个元素都是null - 但是数组本身不是null,因为你传递了两个值.

这可能有点令人费解 - 但实际上:你需要在你的PrintLength方法中检查的不是你Items的整体是否为空 - 而是实际值是否items[0]为空.

可能有点奇怪 - 或者首先是反直觉 - 是将单个显式"null"值视为"null" - 而不是单个null值项的数组.为什么会这样,以及它是否可以以不同的方式实施 - 我不知道,老实说.