87 votes

Quelles interfaces tous les tableaux implémentent-ils en C# ?

En tant que nouveau programmeur .NET 3.5, j'ai commencé à apprendre LINQ et j'ai trouvé quelque chose d'assez basique que je n'avais pas remarqué auparavant :

Le livre affirme que chaque tableau implémente IEnumerable<T> (évidemment, sinon nous ne pourrions pas utiliser LINQ to objects sur les tableaux...). Quand j'ai vu cela, je me suis dit que je n'avais jamais vraiment pensé à cela, et je me suis demandé ce que tous les tableaux implémentent d'autre - j'ai donc examiné les éléments suivants System.Array en utilisant le navigateur d'objets (puisque c'est la classe de base pour tous les tableaux dans le CLR) et, à ma grande surprise, elle n'implémente pas IEnumerable<T> .

Ma question est donc la suivante : où se trouve la définition ? Je veux dire, comment puis-je savoir exactement quelles interfaces chaque tableau implémente ?

85voto

BoltClock Points 249668

De la documentation (c'est moi qui souligne) :

[...] la classe Array implémente la fonction System.Collections.Generic.IList<T> , System.Collections.Generic.ICollection<T> y System.Collections.Generic.IEnumerable<T> interfaces génériques. Les implémentations sont fournies aux tableaux au moment de l'exécution, et ne sont donc pas visibles pour les outils de construction de la documentation.

EDIT : comme le souligne Jb Evain dans son commentaire, seuls les vecteurs (tableaux unidimensionnels) implémentent les interfaces génériques. Quant à pourquoi les tableaux multidimensionnels n'implémentent pas les interfaces génériques, je n'en suis pas tout à fait sûr puisqu'ils implémentent leurs homologues non génériques (voir la déclaration de classe ci-dessous).

En System.Array (c'est-à-dire chaque array) implémente également ces interfaces non-génériques :

public abstract class Array : ICloneable, IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable

3 votes

Je dirais : hérite de cette classe non-générique, et donc implémente ces interfaces non-génériques.

0 votes

Je déteste poser des questions stupides, alors j'essaie vraiment de trouver ma réponse sur MSDN d'abord. Cette fois, je l'ai ratée... désolé pour le dérangement et merci pour l'aide.

5 votes

Je n'ai pas rétrogradé, mais seul le type vecteurs (tableaux unidimensionnels) implémente les interfaces génériques. Un type de tableau multidimensionnel ne les implémente pas.

82voto

Hosam Aly Points 14797

Vous pouvez trouver la réponse à votre question de manière empirique en utilisant un petit extrait de code :

foreach (var type in (new int[0]).GetType().GetInterfaces())
    Console.WriteLine(type);

L'exécution de l'extrait ci-dessus produirait le résultat suivant (sur l'écran d'accueil) .NET 4.0 ):

System.ICloneable
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]

( `1 signifie <T> )

Après .NET 4.5 ( .NET Standard 1.0 et plus), il y a deux interfaces supplémentaires :

System.Collections.Generic.IReadOnlyList`1[System.Int32]
System.Collections.Generic.IReadOnlyCollection`1[System.Int32]

14 votes

+1, bien que j'aurais utilisé typeof(int[]) plutôt que (new int[0].GetType() ...

1 votes

J'aime ça. Il soutient également la citation de la documentation MSDN (comparez ceci avec le résultat de l'itération à travers typeof(Array).GetType().GetInterfaces() où les implémentations génériques sont absentes).

17 votes

@Thomas : Merci pour la suggestion. J'ai préféré utiliser (new int[0]).GetType() pour s'assurer que le résultat inclut tout implémentations fournies aux tableaux au moment de l'exécution comme mentionné par @BoltClock.

57voto

cr7pt0gr4ph7 Points 154

En commençant par .NET 4.5, Les tableaux mettent également en œuvre les interfaces System.Collections.Generic.IReadOnlyList<T> y System.Collections.Generic.IReadOnlyCollection<T> .

Ainsi, en utilisant .NET 4.5, la liste complète des interfaces implémentées par les tableaux devient (obtenue en utilisant la méthode présentée dans La réponse de Hosam Aly ):

System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]
System.Collections.Generic.IReadOnlyList`1[System.Int32]
System.Collections.Generic.IReadOnlyCollection`1[System.Int32]

Étrangement, il semble qu'on ait oublié de mettre à jour le site de la documentation sur MSDN de mentionner ces deux interfaces.

1 votes

Votre lien documentation contient cette information, mais un peu cachée : "À partir de la version 2.0 de .NET Framework, le programme Array met en œuvre la classe System.Collections.Generic.IList<T> , System.Collections.Generic.ICollection<T> y System.Collections.Generic.IEnumerable<T> interfaces génériques. Les implémentations sont fournies aux tableaux au moment de l'exécution et, par conséquent, les interfaces génériques n'apparaissent pas dans la syntaxe de déclaration de la classe Array. "

1voto

Adrian P. Points 31

Attention aux interfaces de tableaux, ils peuvent les implémenter mais en fait ils ne le font pas vraiment... Regardez le code suivant :

            var x = new int[] { 1, 2, 3, 4, 5 };
        var y = x as IList<int>;
        Console.WriteLine("The IList:" + string.Join(",", y));
        try
        {
            y.RemoveAt(1);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
        Console.WriteLine(string.Join(",", y));

Il produit le résultat suivant : resultado

Ainsi, l'analyse syntaxique fonctionne mais tout n'est pas pris en charge, ce qui est correct du point de vue d'une collection de longueur fixe, mais tout à fait faux si vous croyez vraiment qu'il s'agit d'une liste. C'en est fini du principe de Liskov de SOLID :(.

Pour les tests rapides este vous aidera.

0voto

Kamerton Points 105

J'ai trouvé l'implémentation de la IList<T>, ICollection<T>, IEnumerable<T> dans le SZArrayHelper classe imbriquée du tableau.

Mais je dois vous prévenir - vous y trouverez beaucoup plus de questions...

La référence

Après cela, je n'en ai eu qu'un - there_is_no_array ;)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X