LINQ: Comment déclarer IEnumerable[AnonymousType]?
C'est ma fonction:
private IEnumerable<string> SeachItem(int[] ItemIds)
{
using (var reader = File.OpenText(Application.StartupPath + @"tempA_A.tmp"))
{
var myLine = from line in ReadLines(reader)
where line.Length > 1
let id = int.Parse(line.Split('t')[1])
where ItemIds.Contains(id)
let m = Regex.Match(line, @"^d+t(d+)t.+?t(item[^t]+.ddj)")
where m.Success == true
select new { Text = line, ItemId = id, Path = m.Groups[2].Value };
return myLine;
}
}
j'obtiens une erreur de compilation, parce que "myLine" n'est pas une chaîne IEnumerable et je ne sais pas comment écrire IEnumerable[Anonymous]
"ne peut pas convertir implicitement le système de type'.Collection.Générique.IEnumerable [AnonymousType#1] Système "to".Collection.Générique.IEnumerable [string]'"
5 réponses
Vous ne pouvez pas déclarer IEnumerable<AnonymousType>
parce que le type n'a pas de nom (connu) au moment de la compilation. Donc, si vous voulez utiliser ce type dans une déclaration de fonction, d'en faire un type normal. Ou tout simplement modifier votre requête renvoie un IENumerable<String>
et s'en tenir à ce type.
Ou retour IEnumerable<KeyValuePair<Int32, String>>
en utilisant la déclaration select suivante.
select new KeyValuePair<Int32, String>(id, m.Groups[2].Value)
la signature de La méthode sur SearchItem
indique que la méthode renvoie un IEnumerable<string>
mais le type anonyme déclaré dans votre requête LINQ n'est pas de type string
. Si vous voulez garder la même signature de méthode, vous devez changer votre requête pour sélectionner seulement string
s. par exemple,
return myLine.Select(a => a.Text);
si vous insistez pour retourner les données sélectionnées par votre requête, vous pouvez retourner un IEnumerable<object>
si vous remplacez votre return
déclaration
return myLine.Cast<object>();
alors vous pouvez consommer les objets en utilisant réflexion.
mais vraiment, si vous allez consommer un type anonyme en dehors de la méthode dans laquelle il est déclaré, Vous devriez définir une classe an avoir la méthode retourner un IEnumerable
de la classe. Les types anonymes sont pratiques, mais ils peuvent faire l'objet d'abus.
Je ne recommande pas nécessairement cela... C'est une sorte de subversion du système de type, mais vous pourriez faire ceci:
1) Changez votre signature de méthode pour retourner IEnumerable
(non générique)
2) ajouter un cast par exemple helper:
public static class Extensions{
public static IEnumerable<T> CastByExample<T>(
this IEnumerable sequence,
T example) where T: class
{
foreach (Object o in sequence)
yield return o as T;
}
}
3) alors appelez la méthode quelque chose comme ceci:
var example = new { Text = "", ItemId = 0, Path = "" };
foreach (var x in SeachItem(ids).CastByExample(example))
{
// now you can access the properties of x
Console.WriteLine("{0},{1},{2}", x.Text, x.ItemId, x.Path);
}
et vous êtes finis.
la clé est le fait que si vous créez un type anonyme avec le même ordre, types et noms de propriétés à deux endroits les types seront réutilisés. Sachant cela, vous pouvez utiliser des génériques pour éviter la réflexion.
J'espère que cela aidera Alex
votre fonction essaie de renvoyer IEnumerable
public class SearchItemResult
{
public string Text { get; set; }
public int ItemId { get; set; }
public string Path { get; set; }
}
public IEnumerable<SearchItemResult> SearchItem(int[] itemIds)
{
// ...
IEnumerable<SearchItemResult> results = from ... select new SearchItemResult { ... }
}
cependant, si votre but ultime n'est pas de récupérer une sorte d'objet, et que vous êtes seulement intéressé par, disons, le chemin...alors vous pouvez encore générer un IEnumerable < string>:
IEnumerable<string> lines = from ... select m.Groups[2].Value;
j'espère que cela aidera à clarifier votre compréhension de LINQ, énumérables, et les types anonymes. :)
une chose à retenir est que LINQ
consolidés exécution différée. Ce que cela signifie est que votre LINQ
l'instruction n'est pas réellement exécutée jusqu'à ce que vous itériez sur elle dans un foreach
déclaration ou vous appelez le .ToList()
méthode myLine
.
Pour votre exemple, essayez de changer:
return myLine;
À:
return myLine.ToList();