Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Generic class signature require specifying new() if type T needs instantiation ?

Tags:

c#

generics

I'm writing a Generic class as follows.

public class Foo<T> : 
    where T : Bar, new()
{
    public void MethodInFoo()
    {
        T _t = new T();
    }
}

As you can see the object _t of type T is instantiated at runtime. To support instantiation of generic type T, the language forces me to put new() in the class signature. I'd agree to this if Bar is an abstract class but why does it need to be so if Bar standard non-abstract class with public parameterless constructor.

The compiler prompts with the following message if new() is not found.

Cannot create an instance of the variable type 'T' because it does not have the new() constraint

like image 359
this. __curious_geek Avatar asked Dec 03 '09 13:12

this. __curious_geek


People also ask

Can a generic class be instantiated without specifying an actual type argument?

You can create an instance of a generic class without specifying the actual type argument. An object created in this manner is said to be of a raw type. The Object type is used for unspecified types in raw types.

Can you instantiate a generic type?

A generic type is like a template. You cannot create instances of it unless you specify real types for its generic type parameters. To do this at run time, using reflection, requires the MakeGenericType method.

Which of the following constraint specifies that any type argument in a generic class declaration must have public parameter less constructor?

The new constraint specifies that a type argument in a generic class or method declaration must have a public parameterless constructor.


2 Answers

Because there isn't normally an assumption that the template parameter needs to be [non-abstract and] constructible [via a public parameterless constructor] in order for a Type to match the template parameter definition.

Until you add a :new() constraint on the template:

  • The compiler won't let you construct a T
  • The compiler will let you match T with abstract types or types without a public parameterless constructor

The :Bar bit is orthogonal and means:

  • Don't let people match against types that aren't derived from [or are] Bar
  • Let me cast Ts to Bar or types derived from Bar within the body
  • let me call public and in-scope internal methods of Bar on a T
like image 163
Ruben Bartelink Avatar answered Sep 26 '22 22:09

Ruben Bartelink


Just because the Bar class defines a parameter-less constructor, doesn't mean that everything that is a Bar will do so - there may be a class that inherits from Bar but hides the parameter-less constructor. Such a class would meet the Bar constraint but rightly fail the new() constraint.

(Note that if you make Bar sealed to avoid this possibility, you can (understandably) no longer use it as a generic constraint) - edit attempting this produces compiler error CS0701.

like image 22
AakashM Avatar answered Sep 26 '22 22:09

AakashM