how the generic collection is cleared?

S

SharpCoderMP

hi,

until .net 2.0 i've been writing my own collections derived from
CollectionBase. Now with the generics it is much easier to do that...
but! i have some questions about generic lists of complex objects.
consider this short example:

class MyComplexClass : IDisposable
{
[some_fields]
Bitmap img1, img2;
Font font1, font2;
[and_so_on]

public void Dispose()
{
this.img1.Dispose();
this.img2.Dispose();
this.font1.Dispose();
this.font2.Dispose();
GC.SuppressFinalize(this);
}
}

now what happens when i create a list:
List<MyComplexClass> complexList = new List<MyComplexClass>();
and then use it heavily. What will happen when i clear my list?
complexList.Clear(); ???
when i was using CollectionBase i just overriden OnClear and before
clearing my collection i was calling Dispose method on each of my
objects in the list. so i was sure that memory *is* released.

do i have to implement my own generic list by using IList interface to
so make sere that all my complex objects are disposed on list clear?
 
S

Stoitcho Goutsev \(100\)

SharpCoderMP,

I understand what you mean, but keep in mind that not always removing or
clearing means that the object is garbage; it can still be used somewhere in
the code.

If you need this however giving the fact that your type is reference type
you can still use old CollectionBase instead of creating a whole new
collection from scratch.
 
B

Ben Voigt

SharpCoderMP said:
hi,

until .net 2.0 i've been writing my own collections derived from
CollectionBase. Now with the generics it is much easier to do that...
but! i have some questions about generic lists of complex objects.
consider this short example:

class MyComplexClass : IDisposable
{
[some_fields]
Bitmap img1, img2;
Font font1, font2;
[and_so_on]

public void Dispose()
{
this.img1.Dispose();
this.img2.Dispose();
this.font1.Dispose();
this.font2.Dispose();
GC.SuppressFinalize(this);
}
}

now what happens when i create a list:
List<MyComplexClass> complexList = new List<MyComplexClass>();
and then use it heavily. What will happen when i clear my list?
complexList.Clear(); ???
when i was using CollectionBase i just overriden OnClear and before
clearing my collection i was calling Dispose method on each of my
objects in the list. so i was sure that memory *is* released.

do i have to implement my own generic list by using IList interface to
so make sere that all my complex objects are disposed on list clear?

Derive a class from List<T> and override ICollection.Clear()
 
S

SharpCoderMP

Stoitcho said:
I understand what you mean, but keep in mind that not always removing or
clearing means that the object is garbage; it can still be used somewhere in
the code.
i'm aware of that. but in general in my design concept i use the
collection as the only place where i can "find" my objects. i do not
hold any other references. this is the most intuitive way, at least for
me. it would be nice if there was a generic collection of IDisposable
objects that could dispose them on clear :) something like
List<T:IDisposable> that would implement List<T:IDisposable>.Clear(bool
disposeAll) :)
but still generics are very useful!
If you need this however giving the fact that your type is reference type
you can still use old CollectionBase instead of creating a whole new
collection from scratch.
it's not so bad - it's just one interface to implement. and using my own
implementation of let's say IList<T> is more useful when it comes to the
..NET 2.0 than having implementation of old fashion CollectionBase.
 
C

chanmm

If the heap memory is not running low and you have sufficient memory just
like to garbage collector to do the job perhaps.

chanmm
 
B

Barry Kelly

SharpCoderMP said:
hi,

until .net 2.0 i've been writing my own collections derived from
CollectionBase. Now with the generics it is much easier to do that...
but! i have some questions about generic lists of complex objects.
consider this short example:

class MyComplexClass : IDisposable
{
[some_fields]
Bitmap img1, img2;
Font font1, font2;
[and_so_on]

public void Dispose()
{
this.img1.Dispose();
this.img2.Dispose();
this.font1.Dispose();
this.font2.Dispose();
GC.SuppressFinalize(this);
}
}

Unless your class has a finalizer (i.e. ~MyComplexClass()), you don't
need to have the call to GC.SuppressFinalize(this). And unless your
class owns a native resource (i.e. an IntPtr and using native Windows
functions through P/Invoke, but not including Font, Bitmap etc. which
are *managed* resources wrapping native resources), you don't need a
finalizer.

I would also consider making a protected virtual Dispose(bool) method
and putting all the Dispose() calls inside it, and calling that method
with Dispose(false) from your public Dispose() method. That way,
descendants can add to the list of objects to dispose, and have a
guarantee that they will be called because they've overridden a virtual
method.
now what happens when i create a list:
List<MyComplexClass> complexList = new List<MyComplexClass>();
and then use it heavily. What will happen when i clear my list?
complexList.Clear(); ???

It will not call Dispose on each item. That probably wouldn't be a
sensible default anyway: automatically calling Dispose implies ownership
semantics on the contained items, but the list might exist for other
reasons.
when i was using CollectionBase i just overriden OnClear and before
clearing my collection i was calling Dispose method on each of my
objects in the list. so i was sure that memory *is* released.

do i have to implement my own generic list by using IList interface to
so make sere that all my complex objects are disposed on list clear?

What you should do is derive from Collection<T>, but add the constraint
that T derives from IDisposable. You can't do this with List<T> because
the methods aren't virtual and you wouldn't have any guarantees that the
overrides are being called. Something like this:

---8<---
public class DisposableCollection<T> : Collection<T>, IDisposable
where T : IDisposable
{
public void Dispose()
{
ClearItems();
}

protected override void ClearItems()
{
foreach (T item in this)
item.Dispose();
base.ClearItems();
}

// You'll also want to override SetItem and RemoveItem
// to get uniform semantics.
}
--->8---

Note that the above list would have complete ownership semantics. Once
something is removed from it, it is disposed and can't be reused.

-- Barry
 
S

SharpCoderMP

Barry said:
I would also consider making a protected virtual Dispose(bool) method
and putting all the Dispose() calls inside it, and calling that method
with Dispose(false) from your public Dispose() method. That way,
descendants can add to the list of objects to dispose, and have a
guarantee that they will be called because they've overridden a virtual
method.
yes i know this - it's one of those things that FxCop likes to complain
really noisy about :) the above code was only to illustrate the idea.
What you should do is derive from Collection<T>, but add the constraint
that T derives from IDisposable. You can't do this with List<T> because
the methods aren't virtual and you wouldn't have any guarantees that the
overrides are being called. Something like this:
[... cut ...]
thanks. this is almost the same solution i've just implemented :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top