Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is the generic type resolved in c#?

Tags:

c#

generics

According to this answer at stackoverflow, the generic type in C# is resolved at runtime.

However, according to this answer, in C#, the generic type is resolved at compile time.

What am I missing here?

In other words, is the type T resolved at compile time or run time?

Update:

Based on Oded's answer, In a case like this, where the type is a closed concrete type (which means it would be resolved at compile time)

class Program
{
    static void Main()
    {
        var t = new Test<int>();
    }  
}

public class Test<T>
{   
}

will the MSIL have the equivalent of

class Program
{
    static void Main()
    {
        var t = new Test();
    }
}

public class Test<int>
{        
}
like image 507
Foo Avatar asked Jul 18 '13 21:07

Foo


People also ask

Is Genericity resolved at compile time?

According to this answer at stackoverflow, the generic type in C# is resolved at runtime. However, according to this answer, in C#, the generic type is resolved at compile time.

What is generic type constraint?

The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type.

Can generic be void?

Currently, void is not allowed as a generic parameter for a type or a method, what makes it hard in some cases to implement a common logic for a method, that's why we have Task and Task<T> for instance.


2 Answers

The problem is that the question is not well-posed. Two people are claiming opposite things: that types are "resolved" at runtime and that types are "resolved" at compile time.

Since they are contradicting each other, they must both mean something different by "resolved".

I do not know what it means for a type to be "resolved". I do know however what overload resolution is. When asked to solve an overload resolution problem that does not involve dynamic, the C# compiler determines which overload to call at compile time, based on the compile time information about the generic type. So for example, if you have:

static void Main()
{
    var d = new D();
    var p = new P<D>();
    p.N(d);//Displays In class B
}


class B
{
    public void M()// Note, not virtual
    {
        Console.WriteLine("In class B");
    }
} 

class D : B
{
    public new void M()// new, not overload
    {
        Console.WriteLine("In class D");
    }
} 

class P<T> where T : B
{
    public  void N(T t)
    {
        t.M();
    }
}

N always calls B.M even if P<T> is instantiated as P<D>. Why? Because the overload resolution problem that determines what the meaning of t.M is must be solved when P<T>.N is compiled, and at that time, the best the compiler knows is that t must be B, so it chooses B.M.

If that's not what you mean by "resolved" then clarify the question.

like image 196
Eric Lippert Avatar answered Oct 21 '22 21:10

Eric Lippert


You are missing the concepts of open and closed generic types.

Essentially, a closed generic type is when you actually specify existing types on a generic parameter/s (or they are inferred by the compiler). For example:

Nullable<int> nulInt;

An open generic type is one where one or more generic type is to be determined during runtime (so, the Nullable<T> class is an example).

like image 37
Oded Avatar answered Oct 21 '22 23:10

Oded