Я очень заинтригован существованием класса ConcurrentBag<T>
в следующей платформе .NET 4.0:
Сумки полезны для хранения объектов, когда упорядочение не имеет значения, и в отличие от наборов, сумки поддерживают дубликаты.
Мой вопрос: как можно реализовать эту идею? Большинство коллекций, с которыми я знаком, в основном составляют (под капотом) некоторую форму массива, в каком порядке не может быть "материя", но есть порядок (именно поэтому, даже если это не нужно, перечисление будет почти всегда проходят неизменную коллекцию, будь то List
, Queue
, Stack
и т.д. в той же последовательности).
Если бы я должен был догадаться, я мог бы предположить, что внутри он мог бы быть Dictionary<T, LinkedList<T>>
; но это на самом деле кажется довольно сомнительным, поскольку не имеет смысла использовать в качестве ключа любой тип T
.
То, что я ожидаю/надеюсь, это то, что на самом деле это уже установленный тип объекта, который уже "разобрался", и что кто-то, кто знает об этом установленном типе, может рассказать мне об этом. Это так необычно для меня - одна из тех концепций, которые легко понять в реальной жизни, но трудно перевести на полезный класс в качестве разработчика - вот почему я интересуюсь возможностями.
ИЗМЕНИТЬ
Некоторые респонденты предположили, что a Bag
может быть формой хэш-таблицы внутри. Это была моя первоначальная мысль, но я предвидел две проблемы с этой идеей:
- Хэш-таблица не так полезна, когда у вас нет подходящей функции хэш-кода для рассматриваемого типа.
- Простое отслеживание объекта "счет" в коллекции не совпадает с хранением объекта.
Как предложил Meta-Knight, возможно, пример сделает это более понятным:
public class ExpensiveObject() {
private ExpensiveObject() {
// very intense operations happening in here
}
public ExpensiveObject CreateExpensiveObject() {
return new ExpensiveObject();
}
}
static void Main() {
var expensiveObjects = new ConcurrentBag<ExpensiveObject>();
for (int i = 0; i < 5; i++) {
expensiveObjects.Add(ExpensiveObject.CreateExpensiveObject());
}
// after this point in the code, I want to believe I have 5 new
// expensive objects in my collection
while (expensiveObjects.Count > 0) {
ExpensiveObject expObj = null;
bool objectTaken = expensiveObjects.TryTake(out expObj);
if (objectTaken) {
// here I THINK I am queueing a particular operation to be
// executed on 5 separate threads for 5 separate objects,
// but if ConcurrentBag is a hashtable then I've just received
// the object 5 times and so I am working on the same object
// from 5 threads at the same time!
ThreadPool.QueueUserWorkItem(DoWorkOnExpensiveObject, expObj);
} else {
break;
}
}
}
static void DoWorkOnExpensiveObject(object obj) {
ExpensiveObject expObj = obj as ExpensiveObject;
if (expObj != null) {
// some work to be done
}
}