簡體   English   中英

使用C#匿名類型

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM