3

I want to use a class as key for a dictionary. But the class is large in terms of memory consumption. So, I want to know that when we add an object as key to dictionary, does it only add its reference or full copy is added. As, if the full copy of the object is added then I can just use the hashcode of the object.

V K
  • 1,645
  • 3
  • 26
  • 57
  • 3
    What do you think the term "reference-type" means? Only references to the objects are provided. Anyway a dictionary - which is hashbased - uses the haschode anyway, so you won´t need to use it yourself. You should definitly search for reference-types vs. value-types. – MakePeaceGreatAgain Apr 05 '19 at 08:54

3 Answers3

8

The dictionary stores whatever value is passed in - that's the case for both the key and the value of the entry. For reference types, that value is a reference - there's no cloning involved to copy the object that the reference refers to. Here's an example:

var dictionary = new Dictionary<int, StringBuilder>();
var builder = new StringBuilder("x");
dictionary.Add(5, builder);

// Retrieve the reference from the dictionary and append to it
dictionary[5].Append("y");

Console.WriteLine(builder); // Prints xy

That's showing the value side of things. The key is stored in the same way - as a reference - but there's a caveat here... if you mutate the object that a key refers to, that's fundamentally going to break the dictionary in most cases, as the hash code of the key is computed when the entry is added. Typically you use immutable types (like string) as keys for dictionaries.

Martin Eyles
  • 171
  • 13
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 3
    I think the question was about the **key** specificly, so a `new Dictionary();` will be better as example. – vasily.sib Apr 05 '19 at 09:15
4

Modified answer: The C# Dictionary only stores the references to those Class instances and the Hash Codes of the Key Type. It does not store the actual values themselves.

Dandré
  • 2,053
  • 3
  • 18
  • 38
  • 4
    No, reference types are *not* passed by reference. The reference is passed by value. See https://jonskeet.uk/csharp/parameters.html – Jon Skeet Apr 05 '19 at 09:02
  • 1
    "stores the actual Key and Value objects" Eeehm, doesn´t this contradicts your statement "stores the actual Key and Value objects"? So at least for reference-types the actual objects are **not** passed. – MakePeaceGreatAgain Apr 05 '19 at 09:02
  • Apart from this **where** the instance is actually stored (heap or stack) does not really affect **how** that instance is passed around. – MakePeaceGreatAgain Apr 05 '19 at 09:04
  • In a sense it does. When you do a `dict.Add(key, value)` then you are passing instances around either by value or reference. If it is an `int` it is passed by value. If it is an instance of a class, it is passed by reference. Thus the dictionary receives it as such and stores it as such. – Dandré Apr 05 '19 at 09:06
  • @Dandré: No, you're passing a *reference*, by *value*. Please read the link I posted earlier. (Under your model of the world, how would you talk about a method with a signature of `void Foo(ref string name)`?) – Jon Skeet Apr 05 '19 at 09:09
  • @JonSkeet. Yes, you are passing by reference, you are not passing the actual value/content around. The same way you are not passing a class instance around like a struct but you are passing around the reference to the content. However, I suppose, I could pass the class instance into a method using the `ref` and that is probably where my argument falls flat. So I need to update my terminology. I am so used to saying "passing by ref or by val". – Dandré Apr 05 '19 at 09:14
  • @Dandré: You never pass an *instance* by value or reference. You pass a value (whether that a value type value or a reference) by value, or you pass a variable by reference. – Jon Skeet Apr 05 '19 at 09:28
  • @JonSkeet. Understood and noted. Thanks. – Dandré Apr 05 '19 at 09:32
  • I'd recommend just removing everything after the first paragraph from your answer, as I suspect it will cause more confusion. – Jon Skeet Apr 05 '19 at 09:53
2

In case of reference types, references to the key and value will be stored in entry struct. The difference between key and value is that we use comparer on the key to keep it unique. The only thing that is copied is the pointer (reference) to the memory where that object is.

Reference type in C#

erexo
  • 503
  • 1
  • 6
  • 24
  • 5
    The hash code is *not* used for uniqueness, and can't be, because multiple non-equal objects can have the same hash code. – Jon Skeet Apr 05 '19 at 09:03