This question already has answers here:
What does the keyword "where" in a class declaration do?
(7 answers)
Closed 9 years ago.
In the following piece of code (C# 2.0):
public abstract class ObjectMapperBase< T > where T : new()
{
internal abstract bool UpdateObject( T plainObjectOrginal,
T plainObjectNew,
WebMethod fwm,
IDbTransaction transaction );
}
Inheritor example:
public abstract class OracleObjectMapperBase< T > : ObjectMapperBase< T > where T : new()
{
internal override bool UpdateObject( T plainObjectOrginal,
T plainObjectNew,
WebMethod fwm,
IDbTransaction transaction )
{
// Fancy Reflection code.
}
}
What does the where keyword do?
it is a constraint for generics
MSDN
so the new() constraint says it must have a public parameterless constructor
It specifies a constraint on the generic type parameter T.
The new() constraint specifies that T must have a public default constructor.
You can also stipulate that the type must be a class (or conversely, a struct), that it must implement a given interface, or that it must derive from a particular class.
The where clause is used to specify constraints on the types that can be used as arguments for a type parameter defined in a generic declaration. For example, you can declare a generic class, MyGenericClass, such that the type parameter T implements the IComparable interface:
public class MyGenericClass<T> where T:IComparable { }
In this particular case it says that T must implement a default constructor.
This is a generic type constraint. It means that the generic type T must implement a zero parameter constructor.
The Where keyword is basically a constraint on the objects the class can work on/with.
taken from MSDN "The new() Constraint lets the compiler know that any type argument supplied must have an accessible parameterless constructor"
http://msdn.microsoft.com/en-us/library/6b0scde8(VS.80).aspx
It means the T has to have a public default constructor.
Related
This question already has answers here:
Passing arguments to C# generic new() of templated type
(16 answers)
Closed 9 years ago.
I am making a base class from which other classes can be derived.
public class BaseClass<T> where T
{
public BaseClass()
{
TClassObject = new T("SomeText"); // Error here
}
public T TClassObject { get; set; }
}
'T': cannot provide arguments when creating an instance of a variable type.
What I am missing here.
From MSDN:
The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor.
So it needs to be parameterless. You may want to look at Activator.CreateInstance
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
The where T : new() constraint states that T must have a parameterless constructor. Your code is calling into a constructor that takes a string parameter, and it isn't guaranteed that your T will have such a constructor.
It is not possible in C# to create a constraint on a specific constructor signature. If you need this functionality, you're better off using something like one of the answers in this thread.
I saw this code example and was wondering what the purpose of the new() constraint was:
public class Client<T> : IClient where T : IClientFactory, new()
{
public Client(int UserID){ }
}
That's called a "'new' constraint". Here's the documentation on it.
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.
(Emphasis mine)
Basically, you need it whenever you're creating a new T somewhere in the class, to ensure that you're only able to pass in things which the compiler can create a new instance of.
Client is a collection of T objects, and those T objects must implement the IClientFactory interface and have a public parameterless constructor.
new() means
The type argument must have a public parameterless constructor. When
used together with other constraints, the new() constraint must be
specified last.
Ref Generic Constraints on MSDN
Having these classes:
public interface IDbContextFactory
{
DbContext GetContext();
}
public class Repo<T> : IRepo<T> where T : Entity, new()
{
protected readonly DbContext c;
}
public Repo(IDbContextFactory f)
{
c = f.GetContext();
}
What does the keyword new() (in class Repo<T>) do?
It means that the type T must expose a public, default (i.e. parameterless) constructor. That is, you will be able to construct an instance of T with new T(). It can expose other constructors as well, but this generic constraint makes the default one mandatory.
it means, the entity should have a parameterless public constructor.
see this.
When you use the where keyword on a generic definition you apply a type contraint to the generic paramater. The new() constraint declares that the type, T in this case, must have a default constructor. http://msdn.microsoft.com/en-us/library/sd2w2ew5.aspx
After reading your clarification disguised as an answer I thought I would try and help by clarifying a couple of things.
The code in your orginal question defines an interface that seemes to be used by a disembodied constructor. In between those two denfinitions you have defined a generic class which doesen't seem to do much.
Your question pertains to the generic class and the other two definitions are irrelavent to both the question and the answer.
In C#, given a generic type such as this:
interface IGenericType<T> where T : new()
And a descendant type, such as:
class GenericTypeImplementation<U> : IGenericType<U>
Why do we need to explicitly restrict the generic type U with all the restrictions of the parent type?
class GenericTypeImplementation<U> : IGenericType<U> where U : new()
Am I right in inferring that the issue is in the compiler computing the union of restrictions?
interface IGenericType<T> where T : new()
interface IGenericType2<T> where T : SomeOtherType
class GenericTypeImplementation<U> : IGenericType<U>, IGenericType2<U>
/* Hypothesis: Compiler can't infer U must be "SomeOtherType + new()" */
In my opinion, the compiler could be smart enough to infer the restrictions theoretically. But it shouldn't be so smart, because a too-smart compiler is sometimes dangerous. Developers always need a clear/explicit definition of everything. See this scenario:
(1) there is an interface IFoo<T> where T : new()
(2) a class Foo<T> : IFoo<T> and the new() constraint is added automatically by the compiler(brilliant!)
(3) the class Foo<T> is a very base class in the whole project, class A<T> : Foo<T>, and then class B<T> : A<T>...
(4) Now another developer can hardly realize there is such a constraint by looking into the definition of the class, he will get weird compiling errors(well that's acceptable). But what if they are invoked by reflection? Sometimes the program is correct, because the data meets the restriction by accident.
The compiler is able to to infer that U must be convertible to SomeOtherType and must have a default constructor. It will generate a compiler error for each constraint:
Error 1 The type 'U' must have a public parameterless constructor in order to use it as parameter 'T' in the generic type or method '....IGenericType<T>'
Error 2 The type 'U' must be convertible to '....SomeOtherType' in order to use it as parameter 'T' in the generic type or method '....IGenericType2<T>'
This will also happen with just one of those interfaces implemented as well. The class must successfully implement both interfaces in order to be compiled:
class GenericTypeImplementation<U> : IGenericType<U>, IGenericType2<U>
where U : SomeOtherType, new()
{...}
or as a non-generic type:
class GenericTypeImplementation : IGenericType<SomeType>, IGenericType2<SomeOtherType>
{...}
To mark a class as implementing an interface is not a way of specifying constraints on the generic type parameters of a class; it is a way of requiring that those constraints exist on a new type parameter or that they be satisfied by a supplied type.
Perhaps you could think of it this way: an interface is a constrained set of classes and a generic class is also a constrained set of classes. A generic interface is a constrained set of generic classes. When you say that a generic class implements a generic interface, you are asking the compiler, "Is this generic class strictly within the set specified by this generic interface?" You are not merely intersecting them as a further constrained set of classes.
Because a generic type restriction is on the type parameter of the defining class (U in your example), from a CLR point of view, that is a different type from the type parameter of the interface.
The type parameter of the class need not be the actual type parameter of the interface. It need not even be a simple type, as in:
class Implementation<T> : IGenericType<List<T>> { /* ... */ }
In this case, the compiler recognizes that List<T> satisfies the constraint, and so no further specification is necessary. But without such knowledge about the generic type parameter, the compiler requires you to declare it explicitly.
It is instructive to compare this to the similar but not identical behaviour of generic methods. As with classes that implement interfaces, the type restrictions must be specified with the declaration. There is one notable exception: if the implementation is explicit. In fact, the compiler will generate an error when you try to re-impose the restrictions.
For example, given an interface
interface ISomething {
void DoIt<T>() where T : new();
}
the two correct ways to implement this interface are:
class OneThing : ISomething {
public void DoIt<T>() where T : new() { }
}
class OtherThing : ISomething {
void ISomething.DoIt<T>() { }
}
Leaving out the constraint in OneThing or iserting it in OtherThing produces a compile-time error. Why do we need the constraint in the first implementation and not in the second one? I'd say for the same reason I mentioned above for type constraints on interfaces: in the first implementation, the type T has no relation to the type parameter on the interface method, so it must be made explicit for the method to match the interface method. In the second implementation, the fact that we explicitly declare the interface means that the type parameter T is the exact same one that was used in the interface.
Is it possible for a generic interface's type to be based on a specific parent class?
For example:
public interface IGenericFace<T : BaseClass>
{
}
Obviously the above code doesn't work but if it did, what I'm trying to tell the compiler is that T must be a sub-class of BaseClass. Can that be done, are there plans for it, etc.?
I think it would be useful in terms of a specific project, making sure a generic interface/class isn't used with unintended type(s) at compile time. Or also to sort of self-document: show what kind of type is intended.
public interface IGenericFace<T> where T : SomeBaseClass
What your are referring to is called "Generic Constraints". There are numerous constraints that can be put on a generic type.
Some basic examples are as follows:
where T: struct - The type argument must be a value type. Any value type except Nullable - can be specified. See Using Nullable Types (C# Programming Guide) for more information.
where T : class - The type argument must be a reference type; this applies also to any class, interface, delegate, or array type.
where T : new() - The type argument must have a public parameterless constructor. When used together with other constraints, the new() constraint must be specified last.
where T : <base class name> - The type argument must be or derive from the specified base class.
where T : <interface name> - The type argument must be or implement the specified interface. Multiple interface constraints can be specified. The constraining interface can also be generic.
where T : U - The type argument supplied for T must be or derive from the argument supplied for U. This is called a naked type constraint.
These can also be linked together like this:
C#
public class TestClass<T> where T : MyBaseClass, INotifyPropertyChanged, new() { }
public interface IGenericFace<T> where T : SomeBaseClass
VB
Public Class TestClass(Of T As {MyBaseClass, INotifyPropertyChanged, New})
Public Interface IGenericInterface(Of T As SomeBaseClass)
yes.
public interface IGenericFace<T>
where T : BaseClass
{
}