2014-11-21 15 views
6

Ich habe gesehen, wie man eine ConcurrentDictionary to a Dictionary konvertieren, aber ich habe ein Wörterbuch und möchte in ein ConcurrentDictionary konvertieren. Wie mache ich das? ... noch besser, kann ich die Link-Anweisung als ConcurrentDictionary setzen?Wie konvertiert man ein Wörterbuch in ein ConcurrentDictionary?

var customers = _customerRepo.Query().Select().ToDictionary(x => x.id, x => x); 
+0

Was LINQ-Provider verwenden Sie? Ist das Ergebnis von 'Query()' oder 'Select()' ein IQueryable oder ein IEnumerable? –

Antwort

14

Verwenden ConcurrentDictionary<TKey, TValue> Constructor (IEnumerable<KeyValuePair<TKey, TValue>>) constructor, die wie ein Wörterbuch Objekt annehmen kann:

Dictionary<int, string> dictionary = new Dictionary<int, string>(); 
dictionary.Add(1,"A"); 
dictionary.Add(2, "B"); 

ConcurrentDictionary<int,string> concurrentDictionary = 
      new ConcurrentDictionary<int, string>(dictionary); 

kann ich die LINQ Anweisung ein ConcurrentDictionary zu sein?

Nr. Sie können nicht. . Es gibt keine Erweiterungsmethode zum Erstellen von ConcurrentDictionary in LINQ. Sie können entweder Ihre eigene Erweiterungsmethode erstellen oder den ConcurrentDictionary-Konstruktor in Ihrer LINQ-Abfrage verwenden, während Sie Ergebnisse projizieren.

+0

Nun, Sie könnten die Ergebnisse mit LINQ in ein Wörterbuch projizieren, aber Sie müssten dafür Ihre eigene 'ToConcurrentDictionary'-Erweiterungsmethode schreiben. (Möglicherweise können Sie das Zwischenwörterbuch loswerden und direkt eine 'foreach' einfügen und einen Schlüssel- und Wertselektor-Delegaten übernehmen). –

+0

Sie können * LINQ mit dem von Ihnen erwähnten Konstruktor verwenden. Erstellen Sie ein KeyValuePair aus dem ursprünglichen Enumerable mit dem gewünschten Schlüssel und den gewünschten Werten, und übergeben Sie es dann an den Konstruktor, z. 'myEnumerable = ... Select (Element => new KeyValuePair (item.Id, item); ... new ConcurrentDictionary (myEnumerable);'. Keine Notwendigkeit für ein ForEach, obwohl eine Erweiterungsmethode den Code etwas sauberer machen würde –

2

Eine LINQ-To-Objects-Anweisung ist letztlich ein IEnumerable, damit Sie es an den ConcurrentDictionary Konstruktor übergeben, zB:

var customers = myCustomers.Select(x => new KeyValuePair(x.id, x)); 
var dictionary=new ConcurrentDictionary(customers); 

Dies kann nicht mit anderen Anbietern arbeiten. Linq to Entities zum Beispiel konvertiert die gesamte LINQ-Anweisung in SQL und kann nicht in eine KeyValuePair-Projektion projiziert werden. In diesem Fall können Sie AsEnumerable() oder eine andere Methode zu nennen, die die IQueryable zwingt auszuführen, zB:

var customers = _customerRepo.Customers.Where(...) 
          .AsEnumerable() 
          .Select(x => new KeyValuePair(x.id, x)); 
var dictionary=new ConcurrentDictionary(customers); 

Select() ohne Argumente ist nicht IEnumerable oder IQueryable Verfahren so nehme ich es ein Verfahren durch ein anderes vorgesehen ist ORM. Wenn Select() ein IEnumerable zurück können Sie die erste Option verwenden, sonst kann man AsEnumerable()

+0

Hinweis dass Sie 'AsEnumerable()' [an einem Aufzählungszeichen] (http: // msdn.microsoft.com/en-us/library/vstudio/bb335435(v=vs.100).aspx) und es wird nichts schaden. –

4

verwenden Warum nicht Ihre eigene Erweiterungsmethode schreiben:

public static class ConcurrentDictionaryExtensions { 
    public static ConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer) { 
     if (source == null) throw new ArgumentNullException("source"); 
     if (keySelector == null) throw new ArgumentNullException("keySelector"); 
     if (elementSelector == null) throw new ArgumentNullException("elementSelector"); 

     ConcurrentDictionary<TKey, TElement> d = new ConcurrentDictionary<TKey, TElement>(comparer); 
     foreach (TSource element in source) 
      d.TryAdd(keySelector(element), elementSelector(element)); 

     return d; 
    } 

    public static ConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { 
     return ToConcurrentDictionary<TSource, TKey, TSource>(source, keySelector, IdentityFunction<TSource>.Instance, null); 
    } 

    public static ConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer) { 
     return ToConcurrentDictionary<TSource, TKey, TSource>(source, keySelector, IdentityFunction<TSource>.Instance, comparer); 
    } 

    public static ConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) { 
     return ToConcurrentDictionary<TSource, TKey, TElement>(source, keySelector, elementSelector, null); 
    } 

    internal class IdentityFunction<TElement> { 
     public static Func<TElement, TElement> Instance 
     { 
      get { return x => x; } 
     } 
    } 

} 

einfach angenommen den Code aus dem .Net framework.

0

Oder ein nur haben Methode:

private ConcurrentDictionary<TKey, TValue> ToConcurrent<TKey, TValue>(Dictionary<TKey, TValue> dic) { 
     return new ConcurrentDictionary<TKey, TValue>(dic); 
    } 

und dann tun:

var customers = _customerRepo.Query().Select().ToDictionary(x => x.id, x => x); 
var concurrentDic = ToConcurrent(customers); 

Ich persönlich werde mit der Erweiterung Methode, die ich gerade aktualisiert ...

Verwandte Themen