0

Let's assume we have:

public static class MyClass<T> where T : new()
{
  static MyClass()
  {
    _instance = new T();
  }
  private static T _instance;
  public static T Get() => _instance;
  public static void Set(T instance) => _instance = instance;
}

What happens when we then call:

Foo foo = MyClass<Foo>.Get();
Bar bar = MyClass<Bar>.Get();

Or more specifically, how does that gets compiled..

  • Does this create some sort of Dictionary<Type, [MyClass's implementation with Type as the generic arg]>, such that every call to a member on MyClass<T> would constitute a dictionary lookup?
  • or, does it perform a compile-time analysis to find all possible generic args to MyClass<T>, and create distinct types accordingly, each mapped to its corresponding caller? I imagine this latter case would need support by the JIT to handle reflection scenarios.
  • or, does it work in an entirely different way than those mentioned above?

I'd appreciate if someone could explain this, or refer me to a useful resource.

UPDATE:

I have seen the following questions, along with the answers and references mentioned there.

These resources do offer the valuable insight that only one type is compiled while multiple types could be created by the runtime. Although this insight does add to the context of the question, the question is more concerned about the dynamics of accessing members defined on generic types (for which the runtime has already created specialized types).

In order to not get distracted, I'm mostly interested in the performance perspective for the purpose of micro-optimization.

If I'm to rephrase, let's assume we have MyClass<T> as mentioned in the OC, and then we add:

public static class MyFoo
{
  static MyFoo()
  {
    _instance = new Foo();
  }
  private static Foo _instance;
  public static Foo Get() => _instance;
  public static void Set(Foo instance) => _instance = instance;
}

And then add a thousand more of these MyFoo for different types. Does each of the following lines has exactly the same complexity/performance (when called for a thousand types)?

Foo foo1 = MyClass<Foo>.Get();
Foo foo2 = MyFoo.Get();
Aly Elhaddad
  • 1,913
  • 1
  • 15
  • 31
  • Please [see this post](https://stackoverflow.com/questions/54976683/how-c-sharp-generic-works#:~:text=When%20a%20generic%20type%20is,is%20used%20as%20a%20parameter.). – Trevor Feb 11 '22 at 14:56
  • 1
    Does this answer your question? [Where are generic methods stored?](https://stackoverflow.com/questions/41461595/where-are-generic-methods-stored) – Banana Feb 11 '22 at 15:12
  • The threads mentioned in the comments do offer the insight that there's only one generic type compiled, but multiple ones could be instantiated by the runtime. While the insight is valuable and does add to context of the question, I'm more concerned about the dynamics of accessing members defined in generic types. For each *access* to a member on a generic type, how does the runtime determine which specialized type to access? Does it happen via a hidden dictionary? does it happen via some sort of pointers? how does it actually happen? – Aly Elhaddad Feb 11 '22 at 15:29
  • @Trevor I've updated the question. I hope this makes sense. – Aly Elhaddad Feb 11 '22 at 15:51
  • @JustLearnedIt I've updated the question. I hope this makes sense. – Aly Elhaddad Feb 11 '22 at 15:51
  • "For each access to a member on a generic type, how does the runtime determine which specialized type to access?" There's nothing special about generic types here. If you write `Foo.Get()`, is there a runtime lookup of `Foo` in a dictionary of classes? No, the compiler just calls `Foo.Get()`. Whether the type is generic or not is irrelevant. If you call `MyClass.Get()`, then the compiler just calls `MyClass.Get()`. – Raymond Chen Feb 11 '22 at 15:51
  • @RaymondChen this does make sense. If this could be supported by a reference that explains it more in-depth, I'd be more than grateful. If you've seen the update to my question, do you think that the answer to the last part would be **yes**? – Aly Elhaddad Feb 11 '22 at 16:05
  • The existing links already describe the implementation of generics. After the type is generated, all you have is a method call. So is the question "How are method calls implemented at runtime?" – Raymond Chen Feb 11 '22 at 18:23
  • @RaymondChen more or less, yes, specifically for members defined on generic types. – Aly Elhaddad Feb 11 '22 at 19:09
  • There is no "specifically for members defined on generic types". Whether the type is generic or not does not affect how the method is called. – Raymond Chen Feb 11 '22 at 21:16

0 Answers0