c# - LINQ sélectionnez à partir de la Collection de
Je suis d'essayer d'écrire une simple Select
méthode d'une classe qui hérite de IList
.
public class RowDataCollection : IList<RowData> {
private List<RowData> rowList;
internal RowDataCollection(List<RowData> data) {
rowList = data;
}
//...
}
public RowDataCollection Rows;
public RowDataCollection Select(string colName, object value) {
List<RowData> rowList = from item in Rows
where item[colName].Value == value
select item;
return new RowDataCollection(rowList);
}
Quelques problèmes que je vais avoir:
Première:
- VS2010 rapports
Cannot implicitly convert type 'IEnumerable<RowData>' to 'List<RowData>'. An explicit conversion exists (are you missing a cast?)
OK, d'où la FONTE aller?
Deuxième:
- Quelqu'un pourrait passer dans un invalide
colName
valeur (c'est à direString.IsNullOrEmpty(colName)
) ou un paramètre null(object value == null)
.
Comment pourrais-je gérer la façon dont ma fonction retourne si les paramètres d'entrée ne sont pas valides?
[Résolu]
J'ai édité mon Select
déclaration (même rebaptisée par les suggestions ici). J'ai dû utiliser un switch cast vers le type de données que les données, mais il fonctionne.
public RowDataCollection SelectRow(string colName, object value) {
if (!String.IsNullOrEmpty(colName) && (value != null) && (0 < Rows.Count)) {
switch (Rows[0][colName].GetValueType()) {
case TableDataType.Boolean:
return new RowDataCollection(Rows.Where(r => (bool)r[colName].Value == (bool)value).ToList());
case TableDataType.Character:
return new RowDataCollection(Rows.Where(r => (char)r[colName].Value == (char)value).ToList());
case TableDataType.DateTime:
return new RowDataCollection(Rows.Where(r => (DateTime)r[colName].Value == (DateTime)value).ToList());
case TableDataType.Decimal:
return new RowDataCollection(Rows.Where(r => (Decimal)r[colName].Value == (Decimal)value).ToList());
case TableDataType.Integer:
return new RowDataCollection(Rows.Where(r => (int)r[colName].Value == (int)value).ToList());
case TableDataType.String:
return new RowDataCollection(Rows.Where(r => r[colName].Value.ToString() == value.ToString()).ToList());
}
}
return null;
}
[Résolu (version courte)]
Jon Skeet posté ceci sur le même temps que j'ai posté ma solution, et (comme toujours) son code est beaucoup plus agréable.
public RowDataCollection SelectRow(string colName, object value) {
List<RowData> rowList = Rows.Where(r => r[colName].Value.Equals(value)).ToList();
return new RowDataCollection(rowList);
}
@Jon Skeet: Si jamais je vois votre visage dans la même ligne, à certains logiciels développeur de position que je demande, je vais juste faire demi-tour et rentrer à la maison.
@Tout le monde: Merci pour toute l'aide!
Quelque chose me fait penser que je suis absent quelque pièce essentielle du puzzle à faire de ce LINQ travail. Je n'en ai pas vu une explication encore que les clics avec moi. VOODOO je vous dis!
OriginalL'auteur jp2code | 2011-07-12
Vous devez vous connecter pour publier un commentaire.
Le résultat d'une requête qui n'est pas un
List<T>
, c'est unIEnumerable<T>
. Si vous voulez convertir dans unList<T>
, il suffit d'appelerToList
:Comme il arrive, vous êtes seulement à l'appel de
Where
dans votre requête. Je voudrais réécrire ce que:Je voudrais aussi renommer la méthode de quelque chose qui est évidemment filtrage plutôt que projection, étant donné que ce dernier est le plus courant d'utiliser le terme "sélection" dans LINQ.
Comme pour les paramètres d'entrée - je vous suggère de valider les arguments et renvoie une exception si elles ne sont pas valides:
Ce n'est pas vraiment clair ce que tu veux dire... mais pour LINQ to Objects, vous pouvez toujours mettre un point de rupture dans l'expression lambda.
Je peux regarder mes données et de voir qu'il y a une seule ligne avec un ID de 102, par exemple. Y compris les valeurs,
Rows.Where(item => item["ID"].Value == 102).ToList();
est de retour tout dans maRows
collection. C'est difficile à expliquer sur.- Il vraiment ne de le faire. Je soupçonne que vous êtes à l'incompréhension de votre code, ou vous êtes en train de regarder la collection de mal, ou quelque chose comme ça. Honnêtement,
Where
fonctionne 🙂Euh, oui, ça serait... ça va être de la boxe de la valeur, puis en comparant par référence. J'ai édité la réponse à l'utilisation Équivaut à la place, ce qui devrait être d'accord.
OriginalL'auteur Jon Skeet
Vous obtenez le message d'erreur car les Requêtes LINQ retour IEnumerable, pas de Liste.
Si vous avez besoin d'une Liste, il est assez facile:
OriginalL'auteur Justin Niessner
Vous ne pouvez pas jeter un
IEnumerable<RowData>
à unList<RowData>
, cependant, il existe une fonction de commoditéEnumerable.ToList<T>()
, utilisé comme:Quant à votre deuxième question, une exception se produit lors de la
ToList()
appel que l'expression LINQ est évalué immédiatement. Vous avez quelques options, y compris jeterArgumentException
s ou le retour d'une liste vide. Cela dépend de votre cas d'utilisation. Je vous suggère de simplement lever une exception (en supposant que vous avez quelquesHasColumn()
méthode sur votreRowData
classe):Par votre travail d'édition, une autre approche, si une colonne manquante n'est pas nécessairement un "problème":
RowData
contientHasColumn
maintenant! 🙂OriginalL'auteur user7116
Vous devez les convertir en IQueriable<><>, en appelant ToList();
where
clause de!-1 la
Enumerable.ToList<T>()
est appelé trop tard. @jp2code: le résultat d'un brut LINQ-to-Objets de requête estIEnumerable<T>
oùT
est le type de la dernière instruction. Dans votre cas c'estselect item
, etitem
estRowData
. Par conséquent,rowList
estIEnumerable<RowData>
pasList<RowData>
.OriginalL'auteur Alexander Beletsky