|
Hello everyone,
I want to iterator a Dictionary variable instance, and remove all elements under a specific condition.
Here is my code. My questions about whether the following solution will function correctly?
1. will dic.Remove(key) operation impact keys collection?
2. will dic.Remove(key) operation impact dic[key] operation?
I have such concern is because I heard while interation in the middle, remove any elements inside the Dictionary is dangerous because it will make some reference invalid and impact result. Any ideas?
Dictionary<string, Foo>.KeyCollection keys = dic.Keys;
foreach (string key in keys)
{
if (dic[key].order > 100)
{
dic.Remove(key);
}
}
thanks in advance,
George
|
|
|
|
|
No, you may not alter the contents of a collection while foreach ing it.
|
|
|
|
|
Thanks PIEBALDconsult,
Could you provide some pseudo code which could iterate all elements in a Dictionary and remove the ones under specific condition please?
regards,
George
|
|
|
|
|
Well, judging by your other post, if you want to remove a bunch of entries and reduce the footprint, then copying the items you want from one to a new one ought to be the way to go.
Another way would be to foreach the Dictionary, adding the-keys-you-want-to-remove to a List, then foreach the List removing the entries from the Dictionary.
Or, use .Keys.CopyTo to copy the keys to an array, for the array, and do the tests and removals.
|
|
|
|
|
Thanks PIEBALDconsult,
Keys.CopyTo will copy all the keys elements themselves' value, not only just copy a reference?
regards,
George
|
|
|
|
|
Correct, it will copy each of the keys.
|
|
|
|
|
Thanks PIEBALDconsult,
1.
I agree with your solution. I have a further question, why my code dic.Remove(key) will invalid the loop foreach (string key in keys)? How Dictinoary is designed which will be impacted?
2.
I have read the related document for CopyTo,
http://msdn.microsoft.com/en-us/library/91e2z0hz(VS.80).aspx[^]
I am interested to make some test program to verify the actual value is make a copy, not just the reference, any ideas about how to test?
regards,
George
|
|
|
|
|
1) That's the nature of the beast.
2) Why bother?
|
|
|
|
|
Thanks PIEBALDconsult,
I am interested to learn how Dictionary is designed so that when remove one element, foreach loop will become invalid. Any ideas?
regards,
George
|
|
|
|
|
No, it just is, move along.
|
|
|
|
|
Thanks PIEBALDconsult,
I am interested to know some internals about how Dictionary is implemented. If you have any good resources or documents, please feel free to share with us here.
I think most people are using Dictionary frequently and must be interested.
regards,
George
|
|
|
|
|
If you remove an item from the dictionary, that will invalidate the enumerator that the foreach command is using, so it's not possible to remove items in a loop like that.
Do like this:
List<string> remove = new List<string>();
foreach (KeyValuePair<sting, foo=""> item in dic) if (item.Value.order > 100) remove.Add(item.Key);
foreach (string key in remove) dic.Remove(key);</sting,>
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa!
Cool!
In my original code, I am not foreach the whole Dictionary, just the .Keys of the Dictionary (i.e. using Keys Enumerator, not using Dictionary as a whole Enumerator). In this case, deleting an element will also invaliding the Keys Enumerator? Why?
(Does it because .Keys operations on the Dictionary will prefetch all the pointers to old positions before element removal?)
regards,
George
|
|
|
|
|
George_George wrote: In my original code, I am not foreach the whole Dictionary, just the .Keys of the Dictionary (i.e. using Keys Enumerator, not using Dictionary as a whole Enumerator). In this case, deleting an element will also invaliding the Keys Enumerator? Why?
Because the key collection doesn't exist separately. It reads from the dictionary when you loop through the keys.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa!
I have got your idea.
regards,
George
|
|
|
|
|
If you are using .NET 3.5 then you can use the new .ToList() method that comes with Linq.
.ToList() will return a flat list of the KeyValuePairs in your dictionary.
So you can safely itterate over that list and remove stuff from your dictionary
foreach (var entry in dict.ToList())
if(entry.Value.order > 100)
dict.Remove(entry.Key);
|
|
|
|
|
Thanks for your good idea, Roger!
I need to use .Net 2.0 currently.
regardsm
George
|
|
|
|
|
class A
{
public virtual void F() {}
}
class B: A
{
new private void F() {} // Hides A.F within B
}
class C: B
{
public override void F() {} // Ok, overrides A.F
}
may i knwo whta is
Hides A.F within B
and overrides A.F ??
thanks
|
|
|
|
|
OK
class A
{
public virtual void Message()
{
Console.WriteLine("Original Message");
}
}
class B : A
{
public new void Message()
{
Console.WriteLine("Class B's Message");
}
}
class C : A
{
public override void Message()
{
Console.WriteLine("Class C's Message");
}
}
Then, if you create an instance of each class and call Message() you will get each classes message. But, if you cast them as class A, the results are different:
A myA = new A();
B myB = new B();
C myC = new C();
myA.Message();
myB.Message();
myC.Message();
A myAB = new B();
A myAC = new C();
myAB.Message();
myAC.Message();
When you use NEW it just hides the old method, so if you cast it as the base class it won't be able to see the new method anymore and the original will be called. If you use override, then its like re-writing the original method, so even though it is cast back as it's base class the derived classes method will still be called.
My current favourite word is: I'm starting to run out of fav. words!
-SK Genius
Game Programming articles start - here[ ^]-
modified on Saturday, May 17, 2008 1:21 PM
|
|
|
|
|
Hi,
I have a windows forms app that I want to run from Access 2003(VBA)
that is deployed with clickonce.
The app is to be run online.
I have published the app on a web server and then I
pass a unc path to the Shell command in VBA
to run the app.
The problem is I want to pass commandline arguments
to the .net app.
It seems clickonce does not allow to pass arguments
using UNC path.
So how can I get around this and pass arguments???
Malcolm
|
|
|
|
|
when we install an appliction why we need to right some information to thr registry ?
|
|
|
|
|
|
|
Hello everyone,
I am migrating from C++ to C#. Two questions about memory footprint of Dictionary class object instance.
1.
If I call remove method to remove some elements from the Dictionary, will the memory footprint be reduced? (suppose there is no other reference to the removed item) I have some suspecision that Dictionary is not truly removing the element and just mark a flag or something, which still refer this removed item to block it from GCed.
2.
I have two ideas to reduce memory footprint of Dictionary, one is mentioned in (1), to remove some entries. The other is to create a new Dictionary instance, and insert only necessary items into the new Dictionary instance, and reference only the new Dictionary instance in the future.
Which way is better from memory footprint reduce perspective?
thanks in advance,
George
|
|
|
|
|
George_George wrote: If I call remove method to remove some elements from the Dictionary, will the memory footprint be reduced? (suppose there is no other reference to the removed item) I have some suspecision that Dictionary is not truly removing the element and just mark a flag or something, which still refer this removed item to block it from GCed.
When you remove an item from a dictionary, the key value pair is cleared, but kept. This means that if you store reference types in the dictionary, the reference will be removed. If you store value types in the dictionary, the value is cleared but kept, but that is rarely a problem as value types are small.
If you have made a large structure that you store in a dictionary, removing items would not reduce the memory footprint. But then your problem is that you have constructed a structure that breaks every recommendation, and that it works poorly is not because of a problem with the dictionary.
George_George wrote: The other is to create a new Dictionary instance, and insert only necessary items into the new Dictionary instance, and reference only the new Dictionary instance in the future.
That would only be beneficial if you have removed a huge number of items from the collection.
George_George wrote: Which way is better from memory footprint reduce perspective?
Do you think that you have an actual memory footprint problem?
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|