使用C#匿名类型
我正在调用一个返回包含ac#Anonymous Type对象的List变量的方法。 例如:
List list = new List(); foreach ( Contact c in allContacts ) { list.Add( new { ContactID = c.ContactID, FullName = c.FullName }); } return list;
我如何在我正在处理的代码中引用此类型属性,例如
foreach ( object o in list ) { Console.WriteLine( o.ContactID ); }
我知道我的样本是不可能的,我只是这样说,我需要确切地识别匿名类型的每个属性。
谢谢!
方案 :
不只是其中一个答案是正确的和/或建议一个有效的解决方案。 我最终使用了Greg选项3的答案。 我在.NET 4.0中学到了一些非常有趣的东西!
您不能返回匿名类型的列表,它必须是object
列表。 因此,您将丢失类型信息。
选项1
不要使用匿名类型。 如果您尝试在多个方法中使用匿名类型,则创建一个真正的类。
选项2
不要将您的匿名类型转发为object
。 (必须采用一种方法)
var list = allContacts .Select(c => new { c.ContactID, c.FullName }) .ToList(); foreach (var o in list) { Console.WriteLine(o.ContactID); }
选项3
使用dynamic关键字。 (需要.NET 4)
foreach (dynamic o in list) { Console.WriteLine(o.ContactID); }
选项4
使用一些脏reflection。
foreach ( var o in list ) { Console.WriteLine( o.ContactID ); }
这只有当list是IEnumerable
才会起作用,如下所示:
var list = allContacts.Select(c => new { ContactID = c.ContactID, FullName = c.FullName }); }
但是你不能返回匿名类型,因为你必须定义返回类型(你不能返回var
),而匿名类型不能有名字。 你应该创建非匿名类型,如果你要传递它。 实际上,除了查询内部之外,不应该使用过多的匿名类型。
如果您有这样的方法:
List
你不应该真的这样做,但你可以使用一种非常丑陋而且未来的技术:
static T CastByExample(object target, T example) { return (T)target; } // ..... var example = new { ContactID = 0, FullName = "" }; foreach (var o in GetContactInfo()) { var c = CastByExample(o, example); Console.WriteLine(c.ContactID); }
它依赖于事实(可以改变!)编译器为具有相同“形状”(属性名称和类型)的类型重用匿名类型。 由于您的“示例”与方法中类型的“形状”匹配,因此重用相同的类型。
C#4中的动态变量是解决此问题的最佳方法。
您无法使用匿名类型执行此操作。 只需创建一个Contact类/结构并使用它。
List list = new List(); foreach ( Contact c in allContacts ) { list.Add( c ); }
然后你可以这样做:
foreach ( var o in list ) { Console.WriteLine( o.ContactID ); }
…或这个:
foreach ( object o in list ) { Console.WriteLine( ((Contact)o).ContactID ); //Gives intellisense }
当然,在这种情况下你应该创建一个联系人列表而不是一个对象列表:
List list = new List (); foreach ( Contact c in allContacts ) { list.Add( c ); }
编辑:错过了问题的基本部分。 现在修好了。
编辑:再次更改答案。 往上看。
用每个构造的var in替换对象可能有效
我知道我迟到了,但我研究了其他的东西,发现这篇文章回答了你的问题。
可以将对象列表强制转换为匿名类型。
public static void Main() { foreach (object item in GetList()) { var x = Cast(item, new { ContactID = 0, FullName = "" }); Console.WriteLine(x.ContactID + " " + x.FullName); } } public static IEnumerable GetList() { yield return new { ContactID = 4, FullName = "Jack Smith" }; yield return new { ContactID = 5, FullName = "John Doe" }; } public static T Cast(object obj, T type) { return (T)obj; }
列表回来
public static void Main() { foreach (object item in GetList()) { var x = Cast(item, new { ContactID = 0, FullName = "" }); Console.WriteLine(x.ContactID + " " + x.FullName); } } public static IEnumerable GetList() { yield return new { ContactID = 4, FullName = "Jack Smith" }; yield return new { ContactID = 5, FullName = "John Doe" }; } public static T Cast(object obj, T type) { return (T)obj; }
我会用
allContacts .Select(c => new { c.ContactID, c.FullName }) .ToList() .ForEach(c => { ...do stuff; });
然后你根本不需要申报。 我相信较少的声明,较少的分号导致较少的bug
- parellellizing异步调用时如何获得最大出站请求?
- 如何从C#中的QueryPerformanceCounter获取刻度?
- c#打印机属性WMI
- C#4.0中的障碍和C#3.0中的WaitHandle之间的区别?
- IIS抱怨使用LDAP身份validation进行身份模拟
- 如何将4.0引用程序集添加到构建服务器(以便编译器找到它们)?
- 检查我的WPF WebBrowser中的元素,使用“inspect element(s)”(IE,Chrome,Firefox)获取css路径(“copy css-path”)
- WebBrowser控件和Adobe Flash内容
- 支持.NET 4.0“任务并行库”中的进度报告和增量结果