Dois-je privilégier IEnumerable<T> ou des Tableaux?
Dans de nombreux projets, je travaille, à chaque fois que j'ai pour revenir en lecture seule collection, j'utilise le IEnumerable<T>
interface et la rendre type spécifique comme suit:
Public ReadOnly Property GetValues() As IEnumerable(Of Integer)
Get
'code to return the values'
End Get
End Property
La plupart du temps, je retourne une Liste, mais dans certaines fonctions et propriétés en lecture seulement je retourne un tableau qui sert également à bien grâce à l'aimable courtoisie de Méthodes d'Extension.
Ma question est suis-je en violation des principes de conception en retournant IEnumerable<T>
s au lieu de types spécifiques (par exemple: List<T>
, HashSet<T>
, Stack<T>
ou Array
s)?
Vous devez vous connecter pour publier un commentaire.
Je préfère généralement
IEnumerable<T>
ainsi. La chose principale est de se demander ce réel (même minimale) fonctionnalité est retournée à partir de la méthode (ou qui lui sont transmis, dans le cas de l'argument d'une méthode).Si tout ce que vous devez faire est de les énumérer sur un ensemble de résultats, puis
IEnumerable<T>
est exactement ce que fait. Pas plus, pas moins. Cela laisse la possibilité de revenir plusieurs types spécifiques, dans certains cas, en cas de besoin sans casser l'empreinte de la méthode.IEnumerable
peut-être de cacher certains d'exécution afin d'accéder à des éléments alors qu'un[]
ne le sera jamais? c'est à dire. ne les effets secondaires possibles de l'exécution différée l'emportent sur les avantages un peu?David réponse du couvre assez bien il;
IEnumerable<T>
est la meilleure pratique en général. Vous pouvez le voir en regardant la plupart des nouveaux cadre de méthodes.Je voulais juste ajouter que, depuis que vous avez spécifié collection en lecture seule dans votre question initiale, vous pouvez appliquer cela en appelant
.ToList().AsReadOnly()
sur votreIEnumerable<T>
instance avant de le retourner. Cela va créer un béton instance deReadOnlyCollection<T>
pour vous retourner. Votre retour type doit toujours êtreIEnumerable<T>
, car l'appelant n'a pas besoin de savoir que vous êtes spécialement retour d'unReadOnlyCollection<T>
, mais de cette façon, vous éviter l'appelant à partir d'une balle dans le pied.(Sans cette étape, le visiteur pourrait par exemple tenter de jeter le
IEnumerable<T>
il obtient à partir de votre méthode deList<T>
. Si le sort réussit, qui sera, si c'est ce que vous avez à travailler avec, l'appelant peut alors modifier la liste, vous êtes sur l'intérieur de votre méthode, avec éventuellement des conséquences imprévues.)Personnellement, je considère que le retour
IEnumerable<T>
à partir d'une API est une forte indication que la mise en œuvre peut utiliser l'évaluation différée.Sachant que l'évaluation différée peut être utilisé peut être important pour l'appelant, car cela signifie que:
itération sur le résultat plus d'une fois (par exemple, pour obtenir un nombre ensuite accéder aux données) sera le résultat de l'évaluation fait plus d'une fois.
les exceptions peuvent être lancées à partir de l'API lors de l'itération sur le résultat:
par exemple
Si vous ne pensez pas tout de la mise en œuvre aurez besoin d'utiliser l'évaluation différée (par exemple, une Couche d'Accès aux Données de l'API), je préfère retourner
ICollection<T>
ouIList<T>
. En dehors de donner à l'appelant d'accéder à unCount
propriété (ICollection<T>
etIList<T>
) et un indexeur (IList<T>
uniquement), vous êtes également en indiquant clairement qu'il n'y aura pas d'évaluation différée.Lors du retour de votre
ICollection<T>
ouIList<T>
, votre concrètes de mise en œuvre sera probablement habituellement de retour d'unList<T>
. S'il est important que la liste est en lecture seule, puis retourList<T>.AsReadOnly()
Cela dépend de ce que vous voulez faire et ce que vous avez l'intention de "violer".
Cela dépend de:
Tenir à l'esprit que beaucoup de la bonne conception des gourous et des principes préfère retourner IEnumerable<> plus modifiable de la collection de prêt
Retour
IEnumerable<T>
est très bien. Bien que la montre que si T est un type référence, il est possible pour l'utilisateur de modifier l'objet.Vous devez retourner le type qui offre le minimum de fonctionnalités dont vous avez besoin. Dans ce cas, si votre interlocuteur a juste besoin de interate sur les données, puis IEnumerable est plus approprié que
List<T>
,HashSet<T>
ou tout autre type de collection. De cette façon, votre appelant reste dissociée de la mise en œuvre de votre méthode et vous êtes libre de changer vos méthodes de mise en œuvre dans l'avenir sans perturber vos appelants.Si vous n'avez pas besoin de toutes les fonctionnalités supplémentaires fournies par
List<T>
,HashSet<T>
etc ensuite, au retour d'uneIEnumerable<T>
est fine, de l'omi.Retour quel que soit le type que vous sentez le plus approprié; si vous avez seulement besoin de faire une boucle sur les collections ou ne LINQ-y des trucs avec eux, puis
IEnumerable<T>
est bonne dans la plupart des situations.Lorsque vous avez besoin de retourner plus "riche" donc envisager un retour à une interface plutôt qu'un type de béton --
IList<T>
plutôt queList<T>
,ISet<T>
plutôt queHashSet<T>
etc, de sorte que votre application peut changer à l'avenir, si nécessaire, sans casser tout le code appelant.Il dépend. Si vous avez l'intention d'utilisation de votre méthode est simple énumération, IEnumerable est le bon choix.
Si les spécificités de l'index de recherche est important, alors vous pourriez être plus précis.
Cela dit, vous pouvez toujours placer votre IEnumerable dans une expression LINQ et l'utiliser comme quoi que ce soit. Un savant compilateur peut optimiser cette expression si votre retournés type prend déjà en charge la fonction utilisée dans votre expression LINQ.
IEnumerable est plus rapide pour les requêtes qu'il est possible de combiner la logique de requête. En général, je utiliser des tableaux pour la suppression ou la modification des valeurs que je ne veux pas changer ma collection et que je suis affectent