Ma question comme titre ci-dessus. Par exemple,
IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));
mais après tout, il n'a qu'un seul élément à l'intérieur.
Pouvons-nous avoir une méthode comme items.Add(item)
?
comme le List<T>
c#
list
ienumerable
ldsenow
la source
la source
IEnumerable<T>
est destiné à interroger les collections uniquement. C'est l'épine dorsale du framework LINQ. Il est toujours une abstraction d'une autre collection tels queCollection<T>
,List<T>
ouArray
. L'interface fournit uniquement uneGetEnumerator
méthode qui retourne une instanceIEnumerator<T>
qui permet de parcourir la collection étendue un élément à la fois. Les méthodes d'extension LINQ sont limitées par cette interface.IEnumerable<T>
est conçu pour être en lecture seule car il peut représenter une agrégation de parties de plusieurs collections.IList<T>
au lieu deIEnumerable<T>
:IList<T> items = new T[]{new T("msg")}; items.Add(new T("msg2"));
Réponses:
Vous ne pouvez pas, car
IEnumerable<T>
ne représente pas nécessairement une collection à laquelle des éléments peuvent être ajoutés. En fait, ce n'est pas du tout une collection! Par exemple:Ce que vous pouvez faire, cependant, est de créer un nouvel
IEnumerable
objet (de type non spécifié), qui, une fois énuméré, fournira tous les éléments de l'ancien, ainsi que certains des vôtres. Vous utilisezEnumerable.Concat
pour cela:Cela ne changera pas l'objet tableau (vous ne pouvez pas insérer d'éléments dans des tableaux, de toute façon). Mais cela créera un nouvel objet qui listera tous les éléments du tableau, puis "Foo". De plus, ce nouvel objet gardera une trace des changements dans le tableau (c'est-à-dire que chaque fois que vous l'énumérez, vous verrez les valeurs actuelles des éléments).
la source
Concat
soit appelée à plusieurs reprises dans une boucle; et si c'est le cas, vous avez de plus gros problèmes de toute façon, parce que chaque fois que vousConcat
, vous obtenez une couche d'énumérateur supplémentaire - donc à la fin de celui-ci, l'appel uniqueMoveNext
entraînera une chaîne d'appels de longueur égale au nombre d'itérations.IEnumerable<T>
en C #, y compris la surcharge enoperator+
tant queConcat
(au fait, savez-vous qu'en VB, vous pouvez indexerIEnumerable
comme s'il s'agissait d'un tableau - il utiliseElementAt
sous le capot): connect.microsoft.com / VisualStudio / feedback /… . Si nous obtenons également deux surcharges supplémentairesConcat
pour prendre un seul élément à gauche et à droite, cela réduirait la frappexs +=x
- alors allez piquer Mads (Torgersen) pour prioriser cela en C # 5.0 :)Le type
IEnumerable<T>
ne prend pas en charge de telles opérations. Le but de l'IEnumerable<T>
interface est de permettre à un consommateur de visualiser le contenu d'une collection. Ne pas modifier les valeurs.Lorsque vous effectuez des opérations comme .ToList (). Add (), vous créez une nouvelle
List<T>
et ajoutez une valeur à cette liste. Il n'a aucun lien avec la liste d'origine.Ce que vous pouvez faire, c'est utiliser la méthode Ajouter une extension pour en créer un nouveau
IEnumerable<T>
avec la valeur ajoutée.Même dans ce cas, cela ne modifiera pas l'
IEnumerable<T>
objet d' origine . Cela peut être vérifié en y tenant une référence. Par exempleAprès cet ensemble d'opérations, la variable temp ne fera toujours référence qu'à un énumérable avec un seul élément "foo" dans l'ensemble de valeurs tandis que les éléments feront référence à un autre énumérable avec les valeurs "foo" et "bar".
ÉDITER
J'oublie toujours que Add n'est pas une méthode d'extension typique
IEnumerable<T>
car c'est l'une des premières que je finis par définir. C'est icila source
Concat
:)Add
, carAdd
sur pratiquement n'importe quel autre type .NET (pas seulement les collections) mute la collection en place. PeutWith
- être ? Ou cela pourrait même être juste une autre surcharge deConcat
.Concat
surcharge serait probablement un meilleur choix car celaAdd
implique généralement une mutabilité.return e.Concat(Enumerable.Repeat(value,1));
?Avez-vous envisagé d'utiliser
ICollection<T>
ou desIList<T>
interfaces à la place, elles existent pour la seule raison que vous souhaitez avoir uneAdd
méthode sur unIEnumerable<T>
.IEnumerable<T>
est utilisé pour «marquer» un type comme étant ... enfin, énumérable ou simplement une séquence d'éléments sans nécessairement garantir que le véritable objet sous-jacent prend en charge l'ajout / la suppression d'éléments. Souvenez-vous également que ces interfaces implémententIEnumerable<T>
donc vous obtenez également toutes les méthodes d'extensions que vous obtenezIEnumerable<T>
.la source
Quelques méthodes d'extension courtes et douces
IEnumerable
etIEnumerable<T>
faites-le pour moi:Élégant (enfin, sauf pour les versions non génériques). Dommage que ces méthodes ne soient pas dans la BCL.
la source
ToString()
y, car cela capture plus de détails sur l'erreur. Je suppose que vous ne l'avez pas faitinclude System.Linq;
en haut de votre dossier, mais qui sait? Essayez de le découvrir par vous-même, créez un prototype minimum qui présente la même erreur si vous ne le pouvez pas, puis demandez de l'aide dans une question.Dans .net Core, il existe une méthode
Enumerable.Append
qui fait exactement cela.Le code source de la méthode est disponible sur GitHub. .... L'implémentation (plus sophistiquée que les suggestions des autres réponses) vaut le détour :).
la source
Non, l'IEnumerable ne prend pas en charge l'ajout d'éléments.
Votre «alternative» est:
la source
Pour ajouter un deuxième message, vous devez -
la source
Non seulement vous ne pouvez pas ajouter des éléments comme vous le déclarez, mais si vous ajoutez un élément à une
List<T>
(ou à peu près toute autre collection non en lecture seule) pour laquelle vous avez un énumérateur existant, l'énumérateur est invalidé (jetteInvalidOperationException
partir de là).Si vous regroupez les résultats d'un certain type de requête de données, vous pouvez utiliser le
Concat
méthode d'extension:Edit: j'ai utilisé à l'origine l'
Union
extension dans l'exemple, ce qui n'est pas vraiment correct. Mon application l'utilise largement pour s'assurer que les requêtes qui se chevauchent ne reproduisent pas les résultats.la source
Je viens ici pour dire que, à part la
Enumerable.Concat
méthode d'extension, il semble y avoir une autre méthode nomméeEnumerable.Append
dans .NET Core 1.1.1. Ce dernier vous permet de concaténer un seul élément à une séquence existante. Donc, la réponse d'Aamol peut également être écrite commeNéanmoins, veuillez noter que cette fonction ne changera pas la séquence d'entrée, elle renvoie simplement un wrapper qui associe la séquence donnée et l'élément ajouté.
la source
D'autres ont déjà donné de grandes explications sur les raisons pour lesquelles vous ne pouvez pas (et ne devriez pas!) Être en mesure d'ajouter des éléments à un
IEnumerable
. J'ajouterai seulement que si vous cherchez à continuer de coder vers une interface qui représente une collection et que vous voulez une méthode add, vous devez coder versICollection
ouIList
. Comme une aubaine supplémentaire, ces interfaces implémententIEnumerable
.la source
tu peux le faire.
la source
Le moyen le plus simple de le faire est tout simplement
Ensuite, vous pouvez renvoyer la liste sous la forme IEnumerable, car elle implémente l'interface IEnumerable
la source
Si vous créez votre objet comme
IEnumerable<int> Ones = new List<int>();
alors vous pouvez le faire((List<int>)Ones).Add(1);
la source
Bien sûr, vous pouvez (je laisse votre T-business de côté):
la source