me encuentro muy intrigado por la existencia de una clase ConcurrentBag<T>
en el próximo marco .NET 4.0:¿Cómo podría implementarse una clase como. ConcurrentBag <T> de .NET?
Las bolsas son útiles para almacenar objetos Al realizar el pedido, no importa, ya diferencia de conjuntos, bolsas apoyan duplicados.
Mi pregunta es: ¿cómo podría implementarse esta idea? La mayoría de las colecciones con las que estoy familiarizado equivalen esencialmente (bajo el capó) a algún tipo de matriz, en cuyo orden puede no "importarse", pero hay en una orden (por lo que, aunque no es necesario, la enumeración pasará casi siempre a través de una colección sin cambios, ya sea List
, Queue
, Stack
, etc. en la misma secuencia).
Si tuviera que adivinar, podría sugerir que internamente podría ser Dictionary<T, LinkedList<T>>
; pero eso en realidad parece bastante dudoso considerando que no tendría sentido usar solo tipo T
como clave.
Lo que estoy esperando/esperando es que este sea en realidad un tipo de objeto establecido que ya ha sido "descifrado" en alguna parte, y que alguien que conozca este tipo establecido pueda contarme al respecto. Es tan inusual para mí, uno de esos conceptos que es fácil de entender en la vida real, pero que es difícil de traducir en una clase utilizable como desarrollador, y por eso tengo curiosidad sobre las posibilidades.
EDITAR:
Algunos respondedores han sugerido que un Bag
podría ser una forma de una tabla hash interna. Este fue mi primer pensamiento, así, pero previó dos problemas con esta idea:
- Una tabla hash no es del todo útil cuando usted no tiene una función de código hash adecuada para el tipo de que se trate.
- Simplemente rastrear el "recuento" de un objeto en una colección no es lo mismo que almacenar el objeto.
Como Meta-Knight sugirió, tal vez un ejemplo sería hacer esto más claro:
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
}
}
+1, ya que es bueno saber la existencia de esta clase – Konamiman
Dan-o: Su comentario de 5 líneas en su código de ejemplo no tiene sentido. Por supuesto que tiene 5 objetos independientes en la bolsa en ese punto ... el "nuevo" operador en [public ExpensiveObject CreateExpensiveObject()] lo garantiza. – Boogaloo
mmm .. mi error. No he usado hashes en el pasado. Había supuesto que el generador de hash predeterminado crearía un valor de hash único por objeto, que podría anular con su propio generador de hash. No me molestes :) – Boogaloo