|
dojohansen wrote: I don't understand where generics enter into the problem at all. You want to compare two TCell instances, and TCell is apparently not the generic type
TCell is a generic type in the example shown by OP.
dojohansen wrote: Just overriding Equals or the equals operator should suffice.
You may need to override GetHashCode() as well.
Best wishes,
Navaneeth
|
|
|
|
|
N a v a n e e t h wrote: TCell is a generic type in the example shown by OP.
OK, re-reading it I see a mention of "CallMap takes a generic type", and I realize that does make a difference in this case.
N a v a n e e t h wrote: ou may need to override GetHashCode() as well.
Not in order to get the comparison he wants, but yes, it is probably not a good idea to consider objects equal based on value comparison yet still create hash codes based on the reference!
A solution then would be something like
class TCell<T>
{
int n;
string s;
public TCell(int n, string s)
{
this.n = n;
this.s = s;
}
public bool Equals<T2>(TCell<T2> obj)
{
return (obj != null && obj.n == this.n && obj.s == this.s);
}
public override int GetHashCode()
{
return s.GetHashCode();
}
}
HTH
|
|
|
|
|
Oops again tho!
Since there is no appropriate Equals method for us to override, we are in fact only overloading it. Hence there's no sense in overriding GetHashCode() after all, or at least if we do so we should still override Equals(object).
|
|
|
|
|
To add an instance of a class to a collection I might have:
ArrayList myAL = new ArrayList();
MyClass MyObject;
myAL.Add( MyObject );
myAl[0] = new MyClass();
The question is if I use myAL.RomveAt(0) how do I delete the object created with new - remembering that I want to keep the array list.
Thanks.
|
|
|
|
|
Maybe I'm missing something, but the ArrayList is still valid, the object is just removed from it.
The object at index 0 will be picked up by the garbage collector;
only two letters away from being an asset
|
|
|
|
|
The problem is that the entry in the ArrayList is a pointer to the object and I will be dealing with an awful lot of entries using a lot of memory (I estimate the project will take up to 200MB in operation) so I'm being cautious.
|
|
|
|
|
As Mark said, plus some comments:
1.
if MyClass has a public Dispose() method (e.g. when it is a Form, a Font, a Pen, ...), you should call it on the object you no longer need, like so:
MyClass toBeDisposed=myAL[0];
myAL[0]=new MyClass();
toBeDisposed.Dispose();
2.
why do you still use ArrayList? it is better to use a generic List (available since .NET 2.0), as that:
- provides type safety (it only accepts what you declare it should accept);
- is faster, it doesn't need casting when using its elements.
Luc Pattyn
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Luc,
it is a pure class there is no Dispose unfortunately.
I used ArrayList as an example, List is a good idea.
This is for analysing broadcast video streams so I am being careful about overheads so would deriving the classes I use from IDisposable lead to significant overheads?
|
|
|
|
|
Trollslayer wrote: would deriving the classes I use from IDisposable lead to significant overheads?
No, an interface only requires you to implement predefined members (such as the Dispose method). You could also set a reference to null and, if needed, force the GC to do its duty with a simple method call. System.GC is a static class that provide a handful of easy to use methods. You have to be conservative about forcing the GC to run so only use it when it is "profitable".
|
|
|
|
|
The Dispose pattern doesn't create significant overhead, it is intended to free memory or other resources in a deterministic way and earlier than the garbage collector would, so using it typically results in better program behavior.
There is a dual recommendation:
- if a class offers a public Dispose() method, call it when the object is no longer needed; the bigger the object's footprint, the more important this could be;
- as a consequence, if you create a class that is using unmanaged resources (e.g. memory allocated in some DLL), then you should provide a Dispose() method.
FYI: C# has a using statement[^] that may help, as it calls Dispose automatically.
Luc Pattyn
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
I'm a little confused... you want to keep the reference to the object you created in your array list, but you want to destroy it? If you destroy it, the reference will no longer be valid anyway.
If you mean you want to destroy the object and not keep a reference, so long as myAL[0] is the only reference, then it will be eligible for garbage collection when you call RemoveAt so will be destroyed automatically at some point (which can't be determined).
As Luc mentioned, if MyClass implements IDisposable then you should call Dispose() on myAL[0] before removing. If not, and MyClass is using unmanaged resources, then you should implement it yourself in MyClass .
|
|
|
|
|
No, when I remove the reference I want to destroy the object.
The problem is that there is going to be a large number of objects using a LOT of memory so I am trying to figure out how to manage this.
In some cases there will be fixed array sizes to I can use a crude approach of creating an object for the required position and then reusing it again but this is not always possible.
|
|
|
|
|
Once there are no references then it will be eligible for collection so you should be OK.
I seem to remember vaguely reports of problems with fragmentation of the Large Object Heap (LOH) causing out of memory issues. I may be wrong (something just rang an alarm bell in my head!), but it may be worth checking out.
|
|
|
|
|
Thanks Dave, I'll probably do that. The fragmentation issue is a good point.
|
|
|
|
|
Yep. objects larger than 85KB are allocated in the LOH, which used to risk fragmentation and an unexpected OutOfMemoryException (often while a lot of memory was free). I had some code that could demonstrate that easily in a matter of milliseconds, however it no longer fails consistently, so I suspect they did something to improve the situation. Not sure what, when, how, and how well though.
FYI: as collections are based on arrays, which grow by doubling their size, they pretty soon end up being large objects (a List<T> is NOT a linked list, it really is an array). So an app that uses lots of lists of more than 20K objects is bound to affect the LOH fragmentation state to some extent.
Luc Pattyn
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
if I use the following:
List<MyClass> list1;
list1 = new List<MyClass>;
list1.Add(new MyClass());
list1[0].num = 3;
list1.RemoveAt(0);
public class MyClass : Object
{
public int num;
public string str;
}
Any suggestions as to how I can force removal of the object or prove that it has been removed?
|
|
|
|
|
It depends...
The way you've written it, yes as the only reference to the MyClass instance was in list1.
It isn't necessarily destroyed immediately, but it will be eventualy.
|
|
|
|
|
List list1;
list1 = new List;
list1.Add(new MyClass());
list1[0].num = 3;
list1[0] = null;
list1.RemoveAt(0);
public class MyClass : Object
{
public int num;
public string str;
}
modified on Saturday, October 17, 2009 7:32 PM
|
|
|
|
|
Nope. calling RemoveAt moves all list entries by one position (a list is built on top of an array), so the old reference gets overwritten right away; setting it to null first does not help, is a waste of time and space.
Luc Pattyn
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
I just corrected it with a comment. Setting a reference to null can be useful in object level reference types, right?
class Test
{
byte[] bigArray;
public void Alloc()
{
bigArray = new byte[100000000];
}
public void Dealloc()
{
bigArray = null;
}
}
|
|
|
|
|
correct.
Setting a reference to null is useful in two similar situations:
1) as a class member, when the member is no longer needed whereas the object itself is still alive;
example: a class representing a compiler, it first parses the input and needs a keyword list for that, then it generates output code, for which the keywords are no longer useful, so the list could be nulled halfway.
2) as a local variable in a method, when the method basically has two parts, and the second half doesn't need all the data that existed in the first half.
Otherwise setting a reference to null doesn't make much sense (i.e. a class member at the end-of-life of the object, or a local variable near the end of the method).
BTW: the same applies to files and streams; it does not make sense to flush them when the next thing you do is close them.
Luc Pattyn
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Trollslayer wrote: list1.RemoveAt(0); // This removes the reference but does it remove the object?
of course it does NOT delete the object, as:
1) RemoveAt() operates on the list, not on the object; how could it, it has no way of knowing whether the object is still required somewhere (e.g. when another reference exists somewhere, maybe in the same or in another list);
2) the GC is typically not invoked by calling a method that removes, deletes, closes, or shrinks something; it may be called by an action that creates a need for memory, most notably the new keyword.
Luc Pattyn
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Trollslayer wrote: Any suggestions as to how I can force removal of the object or prove that it has been removed?
Maybe it's possible to (ab)use a WeakReference to prove that the object has not died yet, but you couldn't accurately use that trick to monitor the lifetime of the object (you could at best poll the IsAlive property in a tight loop, but the time measurement will be inaccurate)
Calling GC.Collect may help to kill the object ealier, but this function only gives a "best effort" guarantee: "Use this method to force the system to try to reclaim the maximum amount of available memory"
|
|
|
|
|
Here's myOpinion:
The main thing to consider is avoiding very large objects. Having large object *graphs* is not a problem, but if a single object is huge the GC will pin it to a memory location and not move it around.
The typical culprit is a huge string. So if for example you have a lot of xml data you want to keep in memory, it's probably better to load a document and keep that in memory than just the string. The document obviously requires much more space, but it is a graph with lots of objects and the memory manager can easily move them around as needed to defragment memory.
The second thing to consider is to avoid unnecessary allocation and deallocation. It looks to me like your code is replacing one object with another object. If the two are of the same type, why not simply change the state of the original object instead of allocating a new one?
Of course, the total amount of memory needed to run your application is only dependant on live instances, but if you put massive pressure on the memory manager everything will slow down because the GC will have to collect garbage very often and perhaps defrag often as well. So if you're getting out of memory exceptions you either simply use too much memory or you have some pinned objects. Pinned objects can cause out of memory exceptions to occur when superficially it seems you have enough memory available. For example, trying to allocate a 1MB string could fail even if there's 100MB available memory, if no continous block of 1MB is available (or can be made available by defragmenting the memory - hence this can only happen if there are pinned objects).
In short: Don't try to "manage" the memory. The GC will do a far better job with that than you can, because the GC has all the information necessary available to it, such as installed system memory, memory used by other appdomains, allocs per second, live instances, how fragmented the memory is, and so on.
|
|
|
|
|
OK, you've all been a great help and this is what I've learned/decided:
ArrayList is not as efficient as List but I will use it for the output table list since it there will be a number of different table types and as long as they have a large number of common methods it is an easy method of keeping the tables in sequence (this is very important for my application).
You have to treat the LOH with respect - I'm using VS2005 for competibility reasons so I don't know if the fragmentation issue is present.
Although you can try to force garbage collection it looks like this is likely to cause more problems than it solves in my case.
Collections use arrays which double to cope with increases in size can cause problems but since I am using collections of objects then it is the references that double so the object overhead probably isn't too bad.
The using statement looks interesting, I'll consider it for the second version of my stream analysis engine.
Reuse of objects - yes, in an application such as the one I am working on processing 4GB video (DBV actually) files the singleton principle of creating an object only if required and then reusing it is very important since I will have arrays of arrays of table - not a two dimensional array of tables.
Oh, there will definitely be a second version of the analysis engine but as the application is commpany confidential I'm not sure what will go into my first article, probably a beginners guide to multi threading user interfaces which as it's own oddities for a beginner to muddle though.
Thanks everyone.
|
|
|
|