[英]Working with C# Anonymous Types
我正在調用一個返回包含ac#Anonymous Type對象的List變量的方法。 例如:
List<object> list = new List<object>();
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中的dynamic
,我學到了一些非常有趣的東西!
您不能返回匿名類型的列表,它必須是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
使用一些臟反射。
foreach ( var o in list ) {
Console.WriteLine( o.ContactID );
}
這只有在list是IEnumerable<anonymous type>
才會起作用,如下所示:
var list = allContacts.Select(c => new {
ContactID = c.ContactID,
FullName = c.FullName
});
}
但是你不能返回匿名類型,因為你必須定義返回類型(你不能返回var
)而匿名類型不能有名字。 你應該創建非匿名類型,如果你要傳遞它。 實際上,除了查詢內部之外,不應該使用過多的匿名類型。
如果您有這樣的方法:
List<object> GetContactInfo() {
List<object> list = new List<object>();
foreach ( Contact c in allContacts ) {
list.Add( new {
ContactID = c.ContactID,
FullName = c.FullName
});
}
return list;
}
你不應該真的這樣做,但你可以使用一種非常丑陋且不具備面向未來的技術:
static T CastByExample<T>(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<object> list = new List<object>();
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<Contact> list = new List<Contact>();
foreach ( Contact c in allContacts ) {
list.Add( c );
}
編輯:錯過了問題的基本部分。 現在修好了。
編輯:再次更改答案。 往上看。
我知道我遲到了,但我研究了其他的東西,發現這篇文章回答了你的問題。
可以將對象列表強制轉換為匿名類型。
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<object> GetList()
{
yield return new { ContactID = 4, FullName = "Jack Smith" };
yield return new { ContactID = 5, FullName = "John Doe" };
}
public static T Cast<T>(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<object> GetList()
{
yield return new { ContactID = 4, FullName = "Jack Smith" };
yield return new { ContactID = 5, FullName = "John Doe" };
}
public static T Cast<T>(object obj, T type)
{
return (T)obj;
}
用每個構造的var in替換對象可能有效
我會用的
allContacts
.Select(c => new { c.ContactID, c.FullName })
.ToList()
.ForEach(c => {
...do stuff;
});
然后你根本不需要申報。 我相信較少的聲明,較少的分號導致較少的bug
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.