What does "T : new()" mean with generics? - c#

i want to understand that code. I think T must be IContinentFactory's implemented class but i don't understand to end of the new() keyword.
class AnimalWorld<T> : IAnimalWorld where T : IContinentFactory, new()
{
.....
}

T: new() means that type T has to have a parameter-less constructor.
By that you actually specify that you can write T param = new T(); in your implementation of AnimalWorld<T>

new() mean that T must have default(parameterless) ctor.
Constraints on Type Parameters (C# Programming Guide)

The constraint new() means that the type T must have a public parameterless instance constructor. This includes all value types, but not all classes. No interface or delegate type can have such a constructor. When the new() constraint is present, T can never be an abstract class.
When new() is present, the following code is allowed inside the class:
T instance = new T();

class AnimalWorld<T> : IAnimalWorld where T : IContinentFactory, new()
Here is what the declaration means:
AnimalWorld is a class with a generic type parameter T
The class AnimalWorld must implement IAnimalWorld
The type parameter T must implement IContinentFactory
The class for the type parameter T must have a no-argument constructor (that's what the new is for).

Related

c# generics with abstract method

I'm trying to implement some generic method for an abstract class as follows :
public abstract class MyAbstractClass : MyBaseObject {
public MyAbstractClass() : base() { } // there is a parameterless constructor...
}
public class MyList<T> where T : MyBaseObject, new() {
// a generic container that is designed for the base class
}
//--- some paint control of mine
public class PaintControl : IDisposable {
public void InitDrawItems(MyList<MyAbstractClass> items) {
// paint items => this is where the compilation error occurs...
}
}
I get the following compilation error :
Error 24 'MyAbstractClass' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'MyList'
Of course, I'd like to use the abstract MyAbstractClass class (which has several children to handle painting accordingly).
Is there a way around this?
EDIT: I did make the class Abstract to make absolutely sure the children actually DO implement the abstract methods.
new() doesn't allow abstract classes and interfaces to be used as T, because they are not instantiable. new() means the generic type must declare a public parameterless constructor eligible for instantiation of an object.
So you have one option, in my opinion:
remove the new() clause, if you are ok with any abstract type derived from MyBaseObject being used with your generic. As your class is indeed abstract and a child of MyBaseObject, that would work just fine.
This is problem is caused by generic type variance. Declaring a concrete type actually creates a new type at compile time. The type parameters in a class can't be converted implicitly between types. There's no inheritance relation between MyList<MyBaseObject> and MyList<MyConcreteObject>.
Conversions are only permitted for generic interfaces or delegates.
There are two ways to fix this - use an interface instead of a concrete class, eg :
class MyList<T>:IList<T> where T : MyBaseObject, new()
{
}
class PaintControl {
public void InitDrawItems<T>(IList<MyAbstractClass> items) //where T:MyAbstractClass,new()
{
//var anItem=new T();
}
}
Or make InitDrawItems itself generic:
public void InitDrawItems<T>(MyList<T> items) where T:MyAbstractClass,new()
{
// No compilation errors here
}
You should remove the new() constraint for T type in MyList, since it's specifying that you can only use types that can be initialize - abstract ones can't.
You can check more details here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
The answer seems a bit of a workaround, but it actually makes lots of sense...
I know for sure which item of the list I am working with (I am looping through items). Since this item has been created, it is FOR SURE a non-abstract class. And hence, I can call the activator for that item, instead of new T() :
public void InitDrawItems(MyList<MyAbstractClass> items)
foreach (var item in items) {
Type type = o.GetType();
// type is definitely NOT abstract, since the object was created, so it is a
// non-abstract child class and I create the right "copy" of the item !
MyAbstractClass newItem = Activator.CreateInstance(type) as MyAbstractClass;
// ... do whatever I need with the item
}
}
NOTE: as for generics, it makes sens that calling new T() isn't allowed for abstract classes. Put it that way : a container of generic abstract items contains items of a derived child class since the abstract parent class cannot be instantiated. So calling new T() would definitely lead to an issue if allowed by the compiler : which child class should it be?!?
As #Martin pointed out in the comments, from the docs:
The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor. To use the new constraint, the type cannot be abstract.
And the code you have written to define MyList<T>:
public class MyList<T> where T : MyBaseObject, new()
says MyList<T> is a generic class where T must have the new constraint (be type that you can instantiate).
So the reason of your compilation error on the code:
public void InitDrawItems(MyList<MyAbstractClass> items)
is because T in this case is MyAbstractClass which is an abstract class which cannot be instantiated.
So you options are as follows:
Make the method generic, like so:
public void InitDrawItems<T>(MyList<T> items) where T : MyAbstractClass, new()
{
// paint items => this is where the compilation error occurs...
}
Remove the new constraint from T in MyList
Make MyAbstractClass a normal class and not abstract.
It's very simple, you can't instantiate an abstract class and so T = MyAbstractClass clashes with the where T : new() constraint.

What does this syntax mean in the declaration of an abstract class?

I suppose that this is an easy question but I couldn't find the right answer.
What means this syntax? I'm kind of confuse about the new() at the end of the line:
public abstract class SomeClass<E> : Controller where E : ISomeInterface, new()
{
//code of the abstract class
}
The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor. To use the new constraint, the type cannot be abstract.
From: http://msdn.microsoft.com/en-us/library/sd2w2ew5.aspx
You're declaring:
an abstract class SomeClass that depends on type E;
where E is ISomeInterface or any type that implements/derives from ISomeInterface and;
has the default parameterless constructor (new constraint).
new() means that you can instanciate class like that var e = new E();
It's not related to being the class abstract. It's a constraint of the generic type parameter, meaning that type argument should have parameterless constructor.
It means that SomeClass is a generic abstract class which inherits from the Controller class.
The generic type E is restriced to implement the interface ISomeInterface and must have a constructor (It should be initialized)

Generic method with class & new() keyword

public class ViewModelBaseEx<T> : ViewModelBase where T : class, new()
{
//...........
}
I found a class like this in a sample. In this class what is the meaning of portion "where T : class, new()". what is the use of class, new() in this method definition.
It means that T must be a reference type (normally a class, interface, delegate or array) (but not a struct) and that it must have a public parameterless constructor T() (so this will rule out all the previous with exception of class).
It is a generic type constraint.
It specifies that whatever T is, it must be a reference type (a class) and it must have a public default parameterless constructor (new()).
This allows people to do this:
var x = new T();
Without the new() constraint, that isn't possible.
Basically class, new() are adding constraints.
class means that it should be of type class (structs etc are not allowed)
new() represents that it must have a public constructor which takes no parameters.
It means that T must be a reference (class) type and that it must also have a public default constructor.
See here for more information: http://msdn.microsoft.com/en-us/library/d5x73970.aspx
class here is to constraint T to be of Class only, i.e, cannot be structure and other value types.
new() here is to constraint T has to have an empty constructor.
for more information on type constraint, look at the MSDN: http://msdn.microsoft.com/en-us/library/d5x73970.aspx
"class" basically means that "T" is a class type (could be a struct as well => primitive type). The "new()" syntax means that "T" is a class that has an empty constructor so in your class you could do something like:
var obj = new T();

regarding the use of new Constraint in c#

i never use new Constraint because the use is not clear to me. here i found one sample but i just do not understand the use. here is the code
class ItemFactory<T> where T : new()
{
public T GetNewItem()
{
return new T();
}
}
public class ItemFactory2<T> where T : IComparable, new()
{
}
so anyone please make me understand the use of new Constraint with small & easy sample for real world use. thanks
This constraint requires that the generic type that is used is non-abstract and that it has a default (parameterless) constructor allowing you to call it.
Working example:
class ItemFactory<T> where T : new()
{
public T GetNewItem()
{
return new T();
}
}
which obviously now will force you to have a parameterless constructor for the type that is passed as generic argument:
var factory1 = new ItemFactory<Guid>(); // OK
var factory2 = new ItemFactory<FileInfo>(); // doesn't compile because FileInfo doesn't have a default constructor
var factory3 = new ItemFactory<Stream>(); // doesn't compile because Stream is an abstract class
Non-working example:
class ItemFactory<T>
{
public T GetNewItem()
{
return new T(); // error here => you cannot call the constructor because you don't know if T possess such constructor
}
}
In addition to Darin's answer, something like this would fail because Bar does not have a parameterless constructor
class ItemFactory<T> where T : new()
{
public T GetNewItem()
{
return new T();
}
}
class Foo : ItemFactory<Bar>
{
}
class Bar
{
public Bar(int a)
{
}
}
Actual error is: 'Bar' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'ItemFactory<T>'
The following would also fail:
class ItemFactory<T>
{
public T GetNewItem()
{
return new T();
}
}
Actual error is: Cannot create an instance of the variable type 'T' because it does not have the new() constraint
The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor.
quoted from the official website
You can read new() as if it is an interface with a constructor. Just like that IComparable specifies that the type T has a method CompareTo, the new constraint specifies that the type T has a public constructor.
In your example, the constraint acts on <T> in the class declaration. In the first case, it requires that the generic T object has a default (parameterless) constructor. In the second example, it requires that T should have a default, parameterless constructor and that it must implement the IComparable interface.

What does new() mean?

There is an AuthenticationBase class in WCF RIA Services. The class definition is as follows:
// assume using System.ServiceModel.DomainServices.Server.ApplicationServices
public abstract class AuthenticationBase<T>
: DomainService, IAuthentication<T>
where T : IUser, new()
What does new() mean in this code?
It's the new constraint.
It specifies that T must not be abstract and must expose a public parameterless constructor in order to be used as a generic type argument for the AuthenticationBase<T> class.
Using the new() keyword requires a default constructor to be defined for said class. Without the keyword, trying to class new() will not compile.
For instance, the following snippet will not compile. The function will try to return a new instance of the parameter.
public T Foo <T> ()
// Compile error without the next line
// where T: new()
{
T newInstance = new T();
return newInstance;
}
This is a generic type constraint. See this MSDN article.
It means that a type used to fill the generic parameter T must have a public and parameterless constructor. If the type does not implement such a constructor, this will result in a compile-time error.
If the new() generic constraint is applied, as in this example, that allows the class or method (the AuthenticationBase<T> class in this case) to call new T(); to construct a new instance of the specified type. There is no other way, short of reflection (this includes using System.Activator, to construct a new object of a generic type.

Categories