2009-06-01 26 views
16

我似乎一遍又一遍地寫這些代碼,並希望看看是否有更好的方式更一般地做到這一點。優雅的方式從對象列表到字典與其中兩個屬性

我開始了與富貴的對象列表

Foo[] foos = GenerateFoos(); 

我認爲要創建一個字典,其中鍵和值是富

這兩種性質

例如:

Dictionary<string, string> fooDict = new Dictionary<string, string>(): 
foreach (Foo foo in foos) 
{ 
    fooDict[foo.Name] = foo.StreetAddress; 
} 

有沒有辦法一般地編寫這段代碼,因爲它看起來像一個基本的模板,其中有一個對象數組,一個關鍵屬性值屬性和一個字典。

有什麼建議嗎?

我使用VS 2005(C#,2.0)

回答

54

使用LINQ:

var fooDict = foos.ToDictionary(x=>x.Name,x=>x.StreetAddress); 

(是的,​​是Dictionary<string, string>


編輯展現疼痛在VS2005中:

Dictionary<string, string> fooDict = 
    Program.ToDictionary<Foo, string, string>(foos, 
     delegate(Foo foo) { return foo.Name; }, 
     delegate(Foo foo) { return foo.StreetAddress; }); 

,你必須(在Program):

public static Dictionary<TKey, TValue> ToDictionary<TSource, TKey, TValue>(
    IEnumerable<TSource> items, 
    Converter<TSource, TKey> keySelector, 
    Converter<TSource, TValue> valueSelector) 
{ 
    Dictionary<TKey, TValue> result = new Dictionary<TKey, TValue>(); 
    foreach (TSource item in items) 
    { 
     result.Add(keySelector(item), valueSelector(item)); 
    } 
    return result; 
} 
+0

任何在VS2005的工作? – leora 2009-06-01 12:05:27

+0

那麼,你可以使用匿名方法和實用程序類寫一些類似的東西,但它可能會比現有的代碼更多的工作... – 2009-06-01 12:08:27

+0

哦,那很好。比我的好多了:( – 2009-06-01 12:18:14

6

如果您正在使用的框架3.5,可以使用ToDictionary擴展:

Dictionary<string, string> fooDict = foos.ToDictionary(f => f.Name, f => f.StreetAddress); 

對於框架2.0,代碼非常簡單因爲它可以。

可以提高性能有點通過指定字典的能力,當你創建它,所以它不會做任何重新分配,而你往裏面:

Dictionary<string, string> fooDict = new Dictionary<string, string>(foos.Count): 
2

沒有LINQ,無,這裏沒有內置的幫手。你可以寫一個,但:

// I forget if you need this delegate definition -- this may be already defined in .NET 2.0 
public delegate R Func<T,R>(T obj); 
public static Dictionary<K,V> BuildDictionary<T,K,V>(IEnumerable<T> objs, Func<T,K> kf, Func<T,V> vf) 
{ 
    Dictionary<K,V> d = new Dictionary<K,V>(); 
    foreach (T obj in objs) 
    { 
     d[kf(obj)] = vf(obj); 
    } 
    return d; 
} 

Dictionary<string, string> fooDict = BuildDictionary(foos, new Func<Foo,string>(delegate(Foo foo) { return foo.Name; }), new Func<Foo,string>(delegate(Foo foo) { return foo.StreetAddress; })); 

它看起來並不幾乎一樣基於LINQ的答案優雅,不是......

1

下面是的.NET 2.0兼容使用的System.Web解決方案.UI.Databinder對屬性名進行反射 - 您會失去編譯時類型檢查。

 public static Dictionary<string, string> ToDictionary<T>(List<T> list, string keyName, string valueName) 
    { 
     Dictionary<string, string> outputDictionary = new Dictionary<string, string>(); 
     foreach (T item in list) 
     { 
      string key = Eval<T, string>(item, keyName); 
      string value = Eval<T, string>(item, valueName); 
      output[key] = value; 
     } 

     return outputDictionary; 
    } 

    public static TOut Eval<TIn, TOut>(TIn source, string propertyName) 
    { 
     object o = DataBinder.GetPropertyValue(source, propertyName); 
     if (o is TOut) 
      return (TOut)o; 

     return default(TOut); 
    } 

你會叫如下:

Dictionary<string, string> fooDict = ToDictionary(foos, "Name", "StreetAddress"); 
相關問題