Disons que j'ai une fonction comme:
void myFunc(List<AClass> theList)
{
string[] stuff = new string[theList.Count];
}
et je passe dans une liste vide.
Est-ce que ça va être un pointeur nul? Ou s'agira-t-il d'un pointeur vers une position aléatoire dans la mémoire qui n'est pas initialisée?
Cela créera un objet de tableau vide. Cet objet est toujours parfaitement valide et occupe un espace non nul en mémoire. Il connaîtra toujours son propre type et le nombre - il n'aura tout simplement aucun élément.
Les tableaux vides sont souvent utiles en tant que collections vides immuables: vous pouvez les réutiliser à l'infini; les tableaux sont intrinsèquement mutables mais seulement en termes de leurs éléments ... et ici nous n'avons aucun élément à changer! Comme les tableaux ne sont pas redimensionnables, un tableau vide est totalement immuable.
Notez qu’il est souvent utile d’avoir un tableau vide au lieu d’une référence null: les méthodes ou propriétés renvoyant des collections doivent presque toujours renvoyer une collection vide plutôt qu’une référence null, car elles fournissent cohérence et uniformité - plutôt que de créer chaque appelant vérifie la nullité. Si vous souhaitez éviter d'allouer plus d'une fois, vous pouvez utiliser:
public static class Arrays<T>
{
private static readonly T[] empty = new T[0];
public static readonly T[] Empty { get { return empty; } }
}
Ensuite, vous pouvez simplement utiliser:
return Arrays<string>.Empty;
(ou autre) lorsque vous devez utiliser une référence à un tableau vide d'un type particulier.
Pourquoi devrait-il? Cela indiquera simplement un tableau de taille 0, ce qui est parfaitement valide.
Je pense que la confusion provient de l'ambiguïté de représenter l'absence de données par un tableau de taille 0 ou une variable définie sur null (la même ambiguïté existe pour les chaînes avec une chaîne vide ou une référence de chaîne définie sur null). Les deux sont des moyens valables d'indiquer une telle absence et il serait sans doute plus logique de n'en avoir qu'un. Ainsi, sur certaines bases de données (Oracle en particulier), une chaîne vide correspond à la valeur NULL et vice versa, et certains langages de programmation (les nouvelles versions de C # en font partie) permettent de spécifier que les références ne doivent jamais être nulles, éliminant ainsi cette ambiguïté.
C'est un bon code. Vous obtiendrez un objet Array ne contenant aucun élément (allocation).
stuff
sera une référence à un tableau de longueur theList.Count
avec toutes les entrées initialisées à default(string)
, qui est null
.
Ce qui suit est dans la spécification du langage C #:
- Les valeurs calculées pour les longueurs de dimension sont validées en tant que suit. Si une ou plusieurs des valeurs sont inférieurs à zéro, un System.OverflowException est levée et aucune autre étape n'est exécutée.
- Une instance de tableau avec les longueurs de dimension données est allouée. Si il n'y a pas assez de mémoire disponible pour allouer la nouvelle instance, un System.OutOfMemoryException est levée et aucune autre étape n'est exécutée.
Donc, pour une longueur de zéro, la mémoire est allouée.
Linq .Concat
lèvera une exception si l'un des arguments est nul (ce qui peut se produire dans mon cas). Je devais donc faire quelque chose comme ça dans mon code:
public string[] ConcatUsers(string[] users1, string[] users2)
{
return (users1 ?? new string[0]).Concat(users2 ?? new string[0]).ToArray();
}
(juste un exemple où un initialiseur de tableau de taille 0 pourrait être utile)
Si theList
est un objet List
réel et est simplement vide, alors theList.Count
retournera 0. Ce qui signifie que la déclaration devient
string[] stuff = new string[0];
En d'autres termes, stuff
sera simplement un tableau (de chaînes) de longueur 0.
Tant que vous vous assurez que votre liste <> que vous transmettez à la méthode a été initialisée quelque part, comme
List<Stuff> myStuff = new List<Stuff>;
la liste ne pointe pas sur null. Ce sera une liste de zéro substance.