开发者

Why does params behave like this?

Output

1

2

null

2

Code

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


This is a fairly frequently asked question. For details, see section 7.4.1 and 7.4.3.1 of the specification.

Briefly: a method with a params array is applicable in either its "normal form" or its "expanded form". That is, you can say

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

When given a call that is applicable in both forms, the compiler always chooses the normal form over the expanded form.

Suppose we chose the expanded form every time both were applicable. Suppose you had

void M(params object[] x) {}

How would you actually pass a null array to this thing if we always chose the expanded form? That would be impossible!

Suppose you said

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

and we always chose the expanded form. What would this do? Well, an array of objects is an object, so this would choose the expanded form -- it would make another array, wrap this thing up in the array, and pass that!

The choice of expanded form over normal form leads to crazy results. Always choosing the normal form over the expanded form is the more sensible thing to do.


It works as designed, I'd say:

PrintLength(s);

You're passing in a single string which is null - inside your method, items will not be null - it's an array of one element - of type string - of value null

PrintLength(s, s);

Same story here - you're passing in two elements, so items in your method will be an array of two strings - both of which are null themselves, but the array is not

PrintLength(null);

This obviously gets interpreted as a single NULL value and thus items is null. You're not passing in an array, nor an element of type string - you're just passing in a null value per se.

PrintLength(null, null);

That's again - an array of two elements, both of which are null - but the array per se is not null, since you're passing in two values.

It's a bit puzzling, maybe - but really: what you need to check for in your PrintLength method is not whether your Items as a whole is null - but whether the actual values items[0] and so forth are null.

What is a bit odd maybe - or counter-intuitive at first - is the fact the single explicit "null" value is treated as a "null" - rather than an array of a single item of value null. Why that is the case, and whether it could have been implemented differently - I don't know, quite honestly.


The PrintLength(null) is passing a null array where as PrintLength(null, null) is passing a string[] with a length of two containing two null string objects. It'd be the same as passing new string[] { null, null }

Hmm reading what I wrote maybe that doesn't actually answer your question shrug.

Edit:

This is probably why: You can send a comma-separated list of arguments of the type specified in the parameter declaration, or an array of arguments of the specified type.

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


As said in answer one:

  • 1: an array of strings with one element in it - the element is null

  • 2: an array of strings with two elements in it, both elements are null

  • null: null is passed into the method, not an array

  • 2: an array of nulls is passed into the method

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜