这是我的功能:
private IEnumerable<string> SeachItem(int[] ItemIds)
{
using (var reader = File.OpenText(Application.StartupPath + @"\temp\A_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;
}
}
Run Code Online (Sandbox Code Playgroud)
我得到一个编译错误,因为"myLine"不是IEnumerable [string]而且我不知道怎么写IEnumerable [匿名]
"无法将类型'System.Collections.Generic.IEnumerable [AnonymousType#1]'隐式转换为'System.Collections.Generic.IEnumerable [string]'"
Dan*_*ner 15
您无法声明,IEnumerable<AnonymousType>因为该类型在构建时没有(已知)名称.因此,如果要在函数声明中使用此类型,请将其设置为普通类型.或者只是修改您的查询以返回IENumerable<String>并坚持使用该类型.
或者IEnumerable<KeyValuePair<Int32, String>>使用以下select语句返回.
select new KeyValuePair<Int32, String>(id, m.Groups[2].Value)
Run Code Online (Sandbox Code Playgroud)
方法签名on SearchItem表示该方法返回一个IEnumerable<string>但在LINQ查询中声明的匿名类型不是类型string.如果要保留相同的方法签名,则必须将查询更改为仅选择stringseg
return myLine.Select(a => a.Text);
Run Code Online (Sandbox Code Playgroud)
如果您坚持要返回查询选择的数据,IEnumerable<object>则可以在更换return语句时返回
return myLine.Cast<object>();
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用反射消耗对象.
但实际上,如果你要在声明它的方法之外使用匿名类型,你应该定义一个类,让方法返回该类的一个IEnumerable.匿名类型是方便的,但它们可能会被滥用.
我不一定推荐这个...它是类型系统的一种颠覆,但你可以这样做:
1)更改您的方法签名以返回IEnumerable(非通用签名)
2)通过示例助手添加一个强制转换:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
3)然后调用这样的方法:
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);
}
Run Code Online (Sandbox Code Playgroud)
你完成了.
关键是,如果您在两个地方创建具有相同顺序,类型和属性名称的匿名类型,则将重用这些类型.知道了这一点,您可以使用泛型来避免反射.
希望这有助于Alex
当您正在执行的LINQ语句实际返回IEnumerable <T>时,您的函数正在尝试返回IEnumerable <string>,其中T是编译时生成的类型.匿名类型并不总是匿名的,因为它们在编译代码后采用特定的具体类型.
然而,匿名类型,因为它们在编译之前是短暂的,只能在它们创建的范围内使用.为了在您提供的示例中支持您的需求,我想最简单的解决方案是创建一个存储结果的简单实体你的查询:
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 { ... }
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您的最终目标不是检索某种对象,并且您只对Path ...感兴趣,那么您仍然可以生成IEnumerable <string>:
IEnumerable<string> lines = from ... select m.Groups[2].Value;
Run Code Online (Sandbox Code Playgroud)
我希望这有助于澄清您对LINQ,enumerables和匿名类型的理解.:)