ArrayList to List<myType> and item disposal

  • Thread starter Thread starter info
  • Start date Start date
I

info

Hi All,


Suppose you need to release unmanaged resources when you remove an
item from a colletction.

We are now using an override of the ArrayList.Remove() method that
dows the job.

We wanted to move to generics but the List<T> collection does not
feature any virtual method.

How should we proceed?

We need to release unmanaged resources immediately and cannot rely on
the GC delayed cleanup.


Thanks!

Alberto
 
Collection<T> provides the necessary virtual methods - but it will be
up to your code to ensure that nothing else (other than the
collection) is still using it when it gets disposed.

Marc
 
Hi Mark, it looked so straightforward but the crude reality is back:

No way to set collection capacity or to resize it: if you need to
store 1,000,000 items, it would require too many re-alloc

Do you know a workaround?

Can I find the Collection<T> class source code somewhere?

Thanks,

Alberto
 
it would require too many re-alloc
The size uses a doubling strategy, so it won't be as bad as you think.
However, if you want to have full control, note that actually the
collection just *wraps* a list (which is created for you normally) -
you could use the alternative constructor.

The following doesn't show a huge increase for doing this... but I
guess it minimises the work of the GC and the amount of excess...

class MyCollection<T> : Collection<T> {
public MyCollection() { }
public MyCollection(int capacity) : base(new List<T>(capacity))
{ }
}

static class Program {

static void Main() {
MyCollection<int> col = new MyCollection<int>();
Fill(col, "Using default sizing");
col = new MyCollection<int>(1000000);
Fill(col, "Preallocating");
}
static void Fill(MyCollection<int> col, string message) {
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 1000000; i++) {
col.Add(i);
}
watch.Stop();
Console.WriteLine(message);
Console.WriteLine(col.Count);
Console.WriteLine(watch.ElapsedMilliseconds);
}
}
 
Nice, but in many cases we resize it to 100,000 and use 90,000. In
your sample this is not possible. In addition resizing would clear the
array contents. I hope that something is changed in .NET 3.5. Do you
know if Collection<T> in .NET 3.5 is more capable?

Thanks again,

Alberto
 
but in many cases we resize it to 100,000 and use 90,000
You mean you want something like List<T>.Capacity? Then add it! See
sample below (the trick here is to keep a handle to the underlying
list that Collection said:
In addition resizing would clear the array contents.
If you want to clear the contents, call Clear();
Do you know if Collection<T> in .NET 3.5 is more capable?
Well, I'm not sure I agree that it is lacking - but Collection<T> is
"red bits" - so there are no changes *at all* in 3.0 or 3.5 (which
just adds extra assemblies - it doesn't update any); likewise there
are no changes in 2.0 SP1 that I am aware of.

Marc

===Sample===

sealed class MyCollection<T> : Collection<T> {
private readonly List<T> baseList;

private MyCollection(List<T> baseList)
: base(baseList) {
this.baseList = baseList;
}
public MyCollection() : this(new List<T>()) { }
public MyCollection(int capacity) : this(new List<T>(capacity))
{ }

public int Capacity {
get {return baseList.Capacity;}
set {baseList.Capacity = value;}
}
}
 
Thanks so much Marc, you are great! Where did you learn these tricks?

I'll try again an let you know.

Thanks!

Alberto
 
Thanks so much Marc
No problem; I'm glad it helped
Where did you learn these tricks?
Trial and error (mainly error...); and by watching / asking questions
on forums like this.

Marc
 
Back
Top