|
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.
|
|
|
|
|
Thanks Guffa,
1.
You always have comprehensive answers. I do not quite understand "the key value pair is cleared, but kept", kept for what? I think the word clear is conflicting to "kept".
2.
Could you provide more descriptions about why based on the above theory, reference types are cleared from memory, but value types are not?
3.
I think when insert value types into Dictionary, it will be value copied, right?
regards,
George
|
|
|
|
|
George_George wrote: I do not quite understand "the key value pair is cleared, but kept", kept for what? I think the word clear is conflicting to "kept".
The key value pairs are kept in an internal array. When you remove an item, the key value pair structure is kept in the array (i.e. the array is not replaced with a smaller array), but the key and value properties are assigned the default value of their respective type.
George_George wrote: Could you provide more descriptions about why based on the above theory, reference types are cleared from memory, but value types are not?
Because the reference types are stored outside the dictionary itself so that they can be garbage collected, while value types are stored in the key value pair structure in the internal array of the dictionary.
George_George wrote: I think when insert value types into Dictionary, it will be value copied, right?
Yes.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
I like your description below,
1.
--------------------
The key value pairs are kept in an internal array. When you remove an item, the key value pair structure is kept in the array (i.e. the array is not replaced with a smaller array), but the key and value properties are assigned the default value of their respective type.
--------------------
My confusion is, if the item is removed, GCed, then its memory is reclaimed and saved. But a new instance of default value of the reference type is created? So, no space saved?
2.
Sounds like the way to reduce memory footprint to maximum is to create a new one and insert only necessary ones. Right?
regards,
George
|
|
|
|
|
George_George wrote: My confusion is, if the item is removed, GCed, then its memory is reclaimed and saved. But a new instance of default value of the reference type is created? So, no space saved?
The default value of a reference is null, so for reference types the reference to the instance is replaced with a null reference.
George_George wrote: Sounds like the way to reduce memory footprint to maximum is to create a new one and insert only necessary ones. Right?
Yes, but only if the dictionary actually has a memory footprint problem. The data that the dictionary needs to keep track of each item is typically 16 bytes. There has to be quite a lot of unused entries before there are so much memory to reclaim that it's worth it. If the dictionary doesn't have that many entries to get rid of, all you accomplish is more work for the garbage collector.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
1.
Guffa wrote: The data that the dictionary needs to keep track of each item is typically 16 bytes.
4 bytes for key reference variable and 4 bytes for value reference variable on a 32-bit machine? And the total should be (8 + 8) 16 bytes for a 64-bit machine?
2.
Guffa wrote: There has to be quite a lot of unused entries before there are so much memory to reclaim that it's worth it.
Why "there are so much memory to reclaim that it's worth it"? Sorry my English is not very good. Could you say in some other words please?
3.
Guffa wrote: If the dictionary doesn't have that many entries to get rid of, all you accomplish is more work for the garbage collector.
Why "all you accomplish is more work for the garbage collector"? Could you say in some other words please?
regards,
George
|
|
|
|
|
George_George wrote: 4 bytes for key reference variable and 4 bytes for value reference variable on a 32-bit machine? And the total should be (8 + 8) 16 bytes for a 64-bit machine?
The structure that the dictionary uses internally to keep track of an item looks like this:
[StructLayout(LayoutKind.Sequential)]
private struct Entry {
public int hashCode;
public int next;
public TKey key;
public TValue value;
}
If the key and value are reference types, this adds up to 16 bytes on a 32-bit system.
George_George wrote: Why "there are so much memory to reclaim that it's worth it"?
The internal array of the dictionary doesn't grow every time you add an item, intead it's size is doubled every time it grows. This means that the dictionary would have to contain at least 50% unused items before you are sure to gain anything at all by moving the items to a new dictionary.
George_George wrote: Why "all you accomplish is more work for the garbage collector"?
Because you would just create a bunch of new objects and release a bunch of old objects, but the amount of memory used would still be the same.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Great Guffa!
1.
next field is used to keep a linked list for all the items which has the same hash code?
2.
So, each reference type variable will use 8 bytes on 32-bit machine, and 16 bytes on a 64-bit machine?
3.
"This means that the dictionary would have to contain at least 50% unused items" -- I am previously a C++ developer. Like vector, it only grows when its capability is the same as its size.
In C#, is it working the same way -- only grow when it is full? Or always keep at least 50% free? I am confused about why do you think a Dictionary is always keeping at least 50% unused items -- I do not agree, I think it should be Dictionary grows 50% each time when it is full? Any comments? Please feel free to correct me if I am wrong.
4.
"but the amount of memory used would still be the same" -- I doubt it and I want to make some tests. For example, if in the old Dictionary, the capability is 10 but used item is only 3. If I create a new Dictionary, and insert the 3 elements into the new Dictionary, I am not sure whether the capability of the new Dictionary is still 10.
What APIs of Dictionary or scenario could be used to make a simple test? I want to make some tests under your ideas to learn more.
regards,
George
|
|
|
|
|