我已使用AnonymousType类型的对象填充了以下列表
List<object> someList = new List<object>(); someList.Add(new { foo = 1 });
我的问题是,我无法强行输入这样的事情:
someList.Where(x=> x.foo == 1);
但是,可以在此列表中:
var someList = new[] { new { foo = 1 } };
解决方法
您可以利用泛型和类型推断为您创建列表:
public static List<T> CreateAnonymousList<T>(params T[] entries) { return new List<T>(entries); }
用法如下:
var someList = CreateAnonymousList(new { foo = 1 },new { foo = 2 },new { foo = 1 }); someList.Where(x => x.foo == 1);
当然,你无法用它做很多事情.您永远无法在代码中强烈地将其键入除var之外的任何内容,或者从您的方法或通常无法使用匿名类型执行的任何操作中将其返回.如果你想做更多,你只需要咬(小)子弹并为你的匿名类型定义一个类.
重读您的问题,您仍然可以在数组上执行LINQ查询:
var someArray = new[]{new { foo = 1 },new { foo = 1 }}; someArray.Where(x => x.foo == 1)
因此,除非您正在修改它(例如通过标准列表< T>操作,如添加或删除),否则没有理由将其转换为List< T>.
我意识到,也许你仍然希望能够将其传回(由于某种原因),并且仍然可以在不知道其匿名类型的情况下对其进行操作.在这种情况下,您可以将其视为动态并在运行时执行操作,但是您丢失了通常使用匿名类型的智能/强类型:
List<dynamic> someDynamicList = new List<dynamic>() {new { foo = 1 },new { foo = 1 }}; someDynamicList.Where(x => x.foo == 1)
Tim Schmelter指出的最后一种方法利用Jon Skeet的CastByExample,但扩展为使用扩展方法转换您的集合:
public static IEnumerable<T> CastByExample<T>(this IEnumerable source,T example) { foreach(object entry in source) yield return (T)entry; } public static IEnumerable CreateAnonymousData() { return new[]{new { foo = 1 },new { foo = 1 }}; }
使用方式如下:
var anonymousData = CreateAnonymousData(); var typedAnonymousData = anonymousData.CastByExample(new { foo = 1 }); typedAnonymousData.Where(x => x.foo == 1);
这利用了在同一个程序集中,使用相同参数名称,类型和顺序声明的匿名类型编译为相同类型的事实.如果你需要从当前组件的外部调用你CreateAnonymousData这将无法正常工作,你必须无处不在,你使用它(保持你的FOO匿名类型的签名添加/更改其签名,您必须无处不在,你使用它,或者你更新“我的时间会很糟糕”.
但我认为现在越来越清楚,最好的解决方案是简单地定义匿名类型的类表示.