开发者

What happens if I initialize an array to size 0?

Let's say I have a function like:

void myFunc(List<AClass> theList)
{
   string[] stuff = new string[theList.Count];
}

and I pass in an empty list.

Will stuff be a null pointer? Or will it be a开发者_如何学Python pointer to some random place in memory that is uninitialized?


It will create an empty array object. This is still a perfectly valid object - and one which takes up a non-zero amount of space in memory. It will still know its own type, and the count - it just won't have any elements.

Empty arrays are often useful to use as immutable empty collections: you can reuse them ad infinitum; arrays are inherently mutable but only in terms of their elements... and here we have no elements to change! As arrays aren't resizable, an empty array is as immutable as an object can be in .NET.

Note that it's often useful to have an empty array instead of a null reference: methods or properties returning collections should almost always return an empty collection rather than a null reference, as it provides consistency and uniformity - rather than making every caller check for nullity. If you want to avoid allocating more than once, you can use:

public static class Arrays<T>
{
    private static readonly T[] empty = new T[0];

    public static readonly T[] Empty { get { return empty; } }
}

Then you can just use:

return Arrays<string>.Empty;

(or whatever) when you need to use a reference to an empty array of a particular type.


Why should it? It will just point to an array of size 0, which is perfectly valid.

I think the confusion here arises from the ambiguity of representing the absence of data either by an array of size 0 or a variable set to null (the same ambiguity exists for strings with an empty string or a string reference set to null). Both are valid ways to indicate such absence and it would arguably make more sense to have only one. Hence, on some databases (Oracle specifically) an empty string equals the NULL value and vices versa and some programming languages (I think, new versions of C# are one of them) allow to specify references to never be null, also eliminating said ambiguity.


This is fine code. You will get an Array object with zero items (allocations) in it.


stuff will be a reference to an array with length theList.Count with all entries initialized to default(string), which is null.


The following is in the C# language specification:

  • The computed values for the dimension lengths are validated as follows. If one or more of the values are less than zero, a System.OverflowException is thrown and no further steps are executed.
  • An array instance with the given dimension lengths is allocated. If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.

So for a length of zero, memory is allocated.


If theList is an actual List object, and is merely empty, then theList.Count is going to return 0. Which means that the declaration becomes

string[] stuff = new string[0];

In other words, stuff will just be an array (of strings) with length 0.


Linq .Concat will throw an exception if any of the arguments is null(which can occur in my case). So I had to do something like this in my code:

public string[] ConcatUsers(string[] users1, string[] users2)
{
    return (users1 ?? new string[0]).Concat(users2 ?? new string[0]).ToArray();
}

(just an example where 0-size array initializer could be useful)


As long as you ensure that your List<> that you actually pass in to the method was initialized somewhere, like

List<Stuff> myStuff = new List<Stuff>;

the list will not point to null. It will be a list of zero Stuffs.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜