bgroenks
bgroenks

Reputation: 1889

How does C# do runtime generics?

One thing that irritates me about Java is the awful implementation of compile-time translation of generic type arguments.

I can observe and understand that the C# implementation is far better, but I'm confused as to how it works.

Essentially, how can you say:

T t = new T()

If you don't know the type of T and therefore don't know the constructor argument requirements?

I can see

Class<T> cl = T.class

or

T[] tarr = new T[0]

but I don't see how you can really create a new instance of T if you don't know the requirements of constructing it?

Upvotes: 1

Views: 218

Answers (4)

Adriano Repetti
Adriano Repetti

Reputation: 67108

Actually you ask the compiler to force T to have a parameterless constructor so he knows you can new T(). For example:

class Test<T>
{
    T Create()
    {
        return new T();
    }
}

It won't compile because the compiler can't be sure that T won't be an abstract class and that it'll have a default constructor. To make it works you have to add a constrain on the real type of T:

class Test<T> where T : new()

Now the compiler will force T to be a non abstract class with a default constructor. For example this code is not valid because the given type is abstract:

abstract class AnotherTest
{
    public void Test()
    {
        Test<Derived> test = new Test<Derived>();
    }
}

Again, if you try to use a class without default constructor the compiler will emit an error:

class AnotherTest
{
    public AnotherTest(string someParameter)
    {
    }

    public void Test()
    {
        Test<Derived> test = new Test<Derived>();
    }
}

With an array it's a little bit different. Actually you simply ask the compiler to reserve the memory for a given number of slots, you do not allocate the memory for that objects (in case of reference types it'll simply put null in each slot).

References on MSDN

Upvotes: 2

Dmitry S.
Dmitry S.

Reputation: 8513

new T() is just a syntactical sugar for Activator.CreateInstance<T>()

Upvotes: 0

Chris Shain
Chris Shain

Reputation: 51359

You can only do new T(); if T is constrained to have a plain, parameterless public constructor, for instance:

public class Foo<T> where T : new() {
    private myT = new T();
}

Additionally, there is no way to specify that any other sort of constructor exist. This is not possible:

// Doesn't work
public class Foo<T> where T : new(String, Int) {
    private myT = new T("Foo", 5);
}

To your other points, this is how you get the type of T at runtime:

var tType = typeof(T);

and creating an array of T doesn't actually create any instances (unless T is a value type, in which case it creates the default value of that type):

// Space for 32 T's, but nothing in the array.
// If T is a value type, like an int for instance, 
// each one would have the default value (0 for int, for example)
var arrayOfT = new T[32];

Upvotes: 4

Douglas
Douglas

Reputation: 54897

You cannot say new T() unless you constrain your generic type to have a parameterless constructor using the where T : new() constraint — see Constraints on Type Parameters.

And there are no “constructor argument requirements”, since the only supported constructor is the parameterless one. You cannot use, say, new T(false) — constraints of the form where T : new(bool) are not allowed.

Upvotes: 2

Related Questions