|
thanx , ...
now ...
i want to filter some rows have the code of "91" and "90" for i.e. in the field of "A" :
so , I added manually , A column in the DataGridView , name "Column1" . now when i import the excel file to this datagridview , the cell rows that have the value of for e.g. 90 and 91 , insert a value for instance 1 , the value of 100 and 101 , insert 2 and so on .
How can i do this ...
(excuse me for my bad english !)
thanx for help !
modified on Tuesday, October 20, 2009 4:04 AM
|
|
|
|
|
When I was designing my type, I forgot that I can't even do a simple comparison between two of the same generic types. There has got to be a way don't you think?
I am working on a simple game where a reusable base class CellMap take a generic type. There is only one minor glitch that I need to take care of before it is completed and ready to be built on. I need to be able to compare two TCells to see if they have the same internal state. I have googled around and have seen some complex examples about how to mimic the functionality of operator overloading but those examples are too messy. All I need is to compare the internal state. What do you think is the best way to go about this?
Note that I only need the comparison in one line in one method, its just one little line of code that is holding me back. That line of code is commented out. I included surrounding code so you can see the context in which it is in.
class CellMap<TCell>
{
...
public void SetMap(TCell[][] newMap, bool redrawAll)
{
CheckIncomingMap(mapWidth, mapHeight, newMap);
if (!redrawAll)
{
for (ushort y = 0; y < mapHeight; y++)
{
for (ushort x = 0; x < mapWidth; x++)
{
bufferMap[x][y] = newMap[x][y];
changedCells.Enqueue(new CellData(x, y, newMap[x][y]));
}
}
CommitBuffer(false);
}
else
{
for (ushort x = 0; x < mapWidth; x++)
newMap[x].CopyTo(bufferMap[x], 0);
CommitBuffer(true);
}
}
...
}
|
|
|
|
|
CaptainSeeSharp wrote: I forgot that I can't even do a simple comparison between two of the same generic types. There has got to be a way don't you think?
Your best bet would be to implement IEquatable(T) or similar interfaces on the cell class and add constraint to CellMap class so that it accepts a cell type that implements only IEquatable(T) . You can use the Equals() method to check the equality.
Best wishes,
Navaneeth
|
|
|
|
|
Three options that spring to mind.
The first is what Navaneeth suggested:
class CellMap<TCell> where TCell : IEquatable<TCell>
{
public void SetMap(TCell[][] newMap, bool redrawAll)
{
/if (newMap[x][y].Equals(bufferMap[x][y])) continue;
}
} The second is similar but a different contraint
class CellMap<TCell> where TCell : class
{
public void SetMap(TCell[][] newMap, bool redrawAll)
{
if (newMap[0][0] == newMap[0][1]) continue;
}
} The last option is to implement a base class that all TCell s must derive from:
class CellMap<TCell> where TCell : CellBase
{
public void SetMap(TCell[][] newMap, bool redrawAll)
{
if (newMap[0][0] == newMap[0][1]) continue;
}
}
class CellBase
{
} I would prefer the last option as I then know how the == operator is implemented.
|
|
|
|
|
I like IEquatable. Its likely that TCell will be a value type.
|
|
|
|
|
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 (not sure why else you would include the snippet to show that CellMap uses TCell).
Just overriding Equals or the equals operator should suffice.
class TCell
{
int field1;
string field2;
override public bool Equals(object other)
{
if (!(other is TCell)) return false;
return (field1 == other.field1 && field2 == other.field2);
}
static public bool operator ==(TCell x, TCell y)
{
return (x.field1 == y.field1 && x.field2 == y.field2);
}
}
The operator overloading syntax is unfamiliar, but it's just a method after all. The compiler will always look for user-defined operator implementations first and use the default implementations only if no user-defined operators exist. So here, since TCell is a class (a reference type), the compiler will use the user-defined == implementation only where an expression compares two objects of declared type TCell, and otherwise use a reference comparison.
(Of course, another possibility is to make TCell a value type, since the default == will then perform a value comparison rather than a reference comparison. But this alone would be no reason to choose to make TCell a value type!)
|
|
|
|
|
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!
|
|
|
|