为什么params表现得像这样?

时间:2010-02-05 21:21:06

标签: 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());
    }    
}

4 个答案:

答案 0 :(得分:28)

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

简要说明:具有params数组的方法适用于“正常形式”或“扩展形式”。也就是说,你可以说

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

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

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

void M(params object[] x) {}

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

假设你说

M(new object[] { "hello" });

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

选择扩展形式而非正常形式会导致疯狂的结果。总是在扩展形式上选择正常形式是更明智的做法。

答案 1 :(得分:5)

它按设计工作,我会说:

  
    

PrintLength(一个或多个);

  

你传入一个null的单个字符串 - 在你的方法中,items为null - 它是一个元素的数组 - 类型为string - 的值为{ {1}}

  
    

PrintLength(s,s);

  

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

  
    

PrintLength(空);

  

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

  
    

PrintLength(null,null);

  

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

这可能有点令人费解 - 但实际上:您需要在items方法中检查的不是您的PrintLength整体是否为空 - 而是实际值{{1等等是空的。

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

答案 2 :(得分:4)

PrintLength(null)传递一个空数组,其中PrintLength(null, null)传递的string[]长度为2,包含两个空string个对象。它与传递new string[] { null, null }

相同

嗯读我写的内容可能实际上并没有回答你的问题耸肩

修改:

这可能是原因:您可以发送以逗号分隔的参数声明中指定类型的参数列表,或者指定类型的参数数组。

http://msdn.microsoft.com/en-us/library/w5zay9db.aspx

答案 3 :(得分:0)

如答案一所述:

  • 1:包含一个元素的字符串数组 - 元素为空

  • 2:包含两个元素的字符串数组,两个元素都为空

  • null:null传递给方法,而不是数组

  • 2:将一个空数组传递给方法