10

The following code allows me to store a value for each type T:

public static class MyDict<T> {
    public static T Value;
}

I can store as many values as there are types and the compiler doesn't know before-head what types I'm going to use. How and where are those static field values stored?

Update: Obviously it's stored in memory, but I want to know about this memory. Is it heap? Is it some special CLR memory? How is it called? What else is stored that way?

Update 2: JITter generates a single implementation MyDict<__Canon> for all reference type arguments of MyDict<T>. Yet, the values are stored separately. I guess that there is still some per-type-argument structure for each type argument, and while thw vtable is linked to the JITted MyDict<__Canon>, the fields are separate. Am I right?

Ark-kun
  • 6,358
  • 2
  • 34
  • 70
  • 8
    The true answer is, "wherever the compiler _wants_ to store them, and what are _you_ going to do about it if you don't like that?" – John Saunders Dec 16 '13 at 14:49
  • 1
    what do you mean where? is "RAM" not the answer you're looking for? – ddavison Dec 16 '13 at 14:49
  • 2
    `MyDict` is not a fully defined type. Each fully defined type of `MyDict` will have its own unique instance of `Value` (e.g. `MyDict`, `MyDict`, and `MyDict` can have a unique value of `Value`). I didn't put this as an answer as I feel this isn't really the question you are asking, but I thought it would still be useful. – Brian Ball Dec 16 '13 at 14:50
  • 2
    @BrianBall I *think* that is the question – asawyer Dec 16 '13 at 14:51
  • 3
    I do not know the answer, but I do find the question interesting. Please don't close. What's especially interesting is that the jitted code is shared for all constructed types with reference types as arguments. – erikkallen Dec 16 '13 at 14:52
  • http://stackoverflow.com/a/337045/43846 – stuartd Dec 16 '13 at 14:53
  • @stuartd: Quite different question. That other question or its answers do not even mention generics, which are in the very focus of this question. – O. R. Mapper Dec 16 '13 at 15:06
  • @O.R.Mapper I wasn't closing the question, just posting a link I thought might be relevant. Generics or not, the answer I linked to says essentially the same as Eric Lippert's answer below, which is good enough for me.. – stuartd Dec 16 '13 at 21:33
  • @stuartd: Sure. Just thought I'd log my reasons to object, in case other users vote for closing, using your link as an alleged duplicate. – O. R. Mapper Dec 16 '13 at 22:13

2 Answers2

15

How and where are those static field values stored?

They are stored in memory at a location of the CLR's choosing.

Obviously it's stored in memory, but I want to know about this memory.

I assume out of curiosity. If you are making a programming decision based on the answer to this question then you are doing something wrong.

Is it heap?

Well it's not stack or registers, that's for sure.

Is it some special CLR memory?

Yep.

What is it called?

The high frequency heap.

What else is stored that way?

vtables. Interface map structures. Method descriptions. And anything else that the CLR believes is going to be accessed frequently, at the sole discretion of the CLR. We are deep in implementation details here.

JITter generates a single implementation MyDict<__Canon> for all reference type arguments of MyDict<T>.

Correct, though this is an implementation detail.

Yet, the values are stored separately.

By "the values" you mean "the values of static fields of each constructed type". Yes.

I guess that there is still some per-type-argument structure for each type argument

Yes, the data has to go somewhere!

the vtable is linked to the JITted MyDict<__Canon>, the fields are separate.

I don't understand what this sentence means, so I am unable to confirm or deny its correctness.

I also wonder whether there is a way to have per-object stores like that. I.e. not generic type + T, but object + T

To clarify, your question is: there is some storage mechanism that associates a generic type C<T> and a given construction C<Foo> with a given static field of C<Foo>. We can think of this as a lookup where the "key" is the tuple (C<T>, Foo, field) and the value is the value of the field. Is there a similar storage mechanism where the key is (C<T>, some arbitrary object, field)?

No. Build it yourself if you need it.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • And if you want to see how the CLR does it you can view [The Shared Source CLI here](http://www.microsoft.com/en-us/download/details.aspx?id=4917). – Scott Chamberlain Dec 16 '13 at 14:56
  • Yes, it's obviously is stored in memory, but maybe that memory has some name. I also wonder whether there is a way to have per-object stores like that. I.e. not `generic type + T`, but `object + T`. – Ark-kun Dec 16 '13 at 15:01
  • @Ark-kun the `object + T` version (actually it is just `object` version, `T` does not matter) is just non-static instance variables. – Scott Chamberlain Dec 16 '13 at 15:04
  • 1
    @ScottChamberlain No. As you've said, instance field is just "object-indexed". Static field of generic type is "type + type"-indexed (`Type1.Value` is different from `Type1.Value` and `Type2.Value`). What I asked in my comment is a value that is "object + type"-indexed. Just like instances of `Dictionary`, but compile-time. – Ark-kun Dec 16 '13 at 15:19
  • @Ark-kun: I've addressed your follow-up questions. – Eric Lippert Dec 16 '13 at 18:18
  • " Is there a similar storage mechanism where the key is (C, some arbitrary object, field)?" A bit different: "Is there a similar storage mechanism where the "key" is (some arbitrary object, field?) and **then** (type T)?" The result of the object-key lookup can be then used to look up values using type-keys many times. Imagine if you could make a generic **instance** field in a **non-generic** class and access it like `obj.Field = 1`. Like a `Dictionary`, but with compile-time type-based lookup instead of runtime' (http://stackoverflow.com/q/14063940/1497385). – Ark-kun Dec 17 '13 at 18:17
  • @Ark-kun: The closest you can get to that is a generic method. – Eric Lippert Dec 17 '13 at 18:18
5

MyDict<T> is not a fully defined type. Each fully defined type of MyDict<T> will have its own unique instance of Value (e.g. MyDict<string>, MyDict<object>, and MyDict<int> can have a unique value of Value).

Also, this isn't special because the type of Value is T, even if the type of Value were DateTime, each fully defined type would still have its own instance of the static value.

Servy
  • 202,030
  • 26
  • 332
  • 449
Brian Ball
  • 12,268
  • 3
  • 40
  • 51
  • 1
    Yes, as I wrote, the instances are different. But I wanted to know where the values are stored. Static field of non-generic type is singleton. Instance field is per-instance. But static field of generic type is per-type-argument. – Ark-kun Dec 16 '13 at 15:21
  • Look at it this way: `Dict` is not a type (not 100% accurate, but for argument sake, let's say it's true), it's a partial. `Dict` is a type, `Dict` is a type. You might as well have called them `DictString` and `DictFoo`. What generics give you is a way of defining a partial type and using placeholders (such as `T`) as blanks. The runtime fills in these blanks for you to save yourself a lot of copy/paste. – Brian Ball Dec 16 '13 at 15:50
  • Also, just an FYI, not all statics are singletons. If you decorate a static with the `ThreadStaticAttribute`, then there is an instance of that particular static field on each thread. – Brian Ball Dec 16 '13 at 15:55