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.
Related
While I understand generic types <T> and where clause for constraint, I was confused about the following code from Unity Tower Defense Template:
public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
What's the purpose of restricting the type to be itself?
It prevents you from doing this:
public class A
{
}
public class B : Singleton<A>
{
}
You will get a compile error. Due to the type constraint, you must write:
public class A : Singleton<A>
{
}
Off the top of my head, one possible benefit of this is allowing methods to return the specific type. This is done by fluent style methods. Another example, obviously not applicable to the example you posted, is a Copy() method that returns a copy of the object as the derived type rather than as its base type. The method signatures of the Singleton< T> class you posted likely show where it uses the T parameter and likely hint at the reason why it uses this pattern.
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
I am trying to create a generic factory-pattern-like mechanism.
The factory will be like:
public class APlugin<ActionType> where ActionType : IAction
{
// create a new action. Note: ActionType should contain
// an empty constructor
public ActionType CreateAction()
{
return Activator.CreateInstance<ActionType>();
}
}
Descendants of IAction might hide the parameterless constructor and this will cause the factory to fail.
You can ensure class has constructor without arguments by providing generic constraint where T : new(). It will affect type T only, though. Containing class will be unaffected, so you can make sure ActionType in your case has said constructor, but you can't enforce it on any class inheriting from APlugin<T>.
You can't force an empty constructor or any type of constructor on derived types.
Constructors do not get inherited, but do get called.
If not chaining to the base constructor (using the : base() syntax), the default base constructor will be called implicitly.
From Using Constructors on MSDN:
In a derived class, if a base-class constructor is not called explicitly using the base keyword, then the default constructor, if there is one, is called implicitly.
Pretty late but i think this is worth knowing..
You can force constructors with 0 parameters on non-abstract classes. This is a type constraint to use whenever you want to enforce those constraints on a class structure. It requires you to specify the type that implements the interface which might be found disturbing. That's the price if you want some neat type safety.
public interface IEmptyConstructor<TThis> where TThis : IEmptyConstructor<TThis>, new() {}
for example a singleton structure
public abstract class Singleton<TThis> : ISingleton where TThis : Singleton<TThis>, new() { /* some singleton madness */ }
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.
I'm trying to add another restriction on a method within a generic class. Is this possible?
Pseudocode:
public class MyBaseClass<T> where T: class
{
public IQueryable<T> ShowThisMethod where T: class, IMyInterface
{
// stuff.
}
}
ShowThisMethod should only be available when T is IMyInterface. Also IMyInterface should then give information back (about T) so that I can access properties defined in IMyInterface inside of the method.
Help :)
By the way, this compiles (and seems "almost right"):
public class MyBaseClass<T> where T: class
{
public IQueryable<T> ShowThisMethod<T>() where T: class, IMyInterface
{
String X = T.MyInterfaceStringProperty;
}
}
More Information about my goal:
I'm using a generic base class to access a common property (DateTime "Time" property on LINQ object Dinner which is also on Lunch).
Both objects are implementing ITimeable which exposes the DateTime property.
In my base class I'd like to have a method Select() which works on IQueryable<T> and can automatically filter based on the Time property. Because I'm working off the generic T, the time property is not visible to the base class, unless I tell it that T is implementing ITimeable.
I do want the same base class to work for other non-ITimeable objects too, that's why I need the interface restriction on the Select method, and I also need it in order to access the Time property using generics.
Hope that clears the goal :)
P.S. My main concern is not visibility of the method in IntelliSense etc.. I'd just like to keep my base class working, while being able to access an interface-specified property through generics in it.
It depends on what you want.
Since the class is compiled once, and the magic with generics also relies on the runtime, there's no way to make a class that has some methods in some cases, and other methods in other cases. Either the methods are there, or they aren't.
So basically, there's no way to declare MyBaseClass so that the following happens:
MyBaseClass<Int32> bc;
bc. <-- intellisense does not show ShowThisMethod here
MyBaseClass<SomeTypeImplementingIMyInterface> bc2;
bc2. <-- intellisense DOES show ShowThisMethod here
... that is... by itself.
You can "trick" the compiler and intellisense into giving you what you're asking for, but know that this gives you other limitations and challenges that might need to be solved.
Basically, by adding an extension method to a static class declared alongside MyBaseClass, you can make intellisense, and the compiler, behave as if the method is only present for MyBaseClass when T has some specific rules, as you're asking for.
However, since the method in question will be a static method, defined outside of MyBaseClass, there's limits to how much of the internals of MyBaseClass you can access, and you can't access the method inside MyBaseClass, so it depends on what you want to accomplish and whether you can live with the limitations or not.
Anyway, here's the extension method. Note that you remove it completely from MyBaseClass at the same time:
public static class MyBaseClassExtensions
{
public static IQueryable<T> ShowThisMethod<T>(this MyBaseClass<T> mbc)
where T: class, IMyInterface
{
...
}
}
Also note that ShowThisMethod is redefining T in the context of ShowThisMethod. It is not the same T as defined by the class.
Specifying a different Type parameter where the new one inherits from the one defined by the class would be the best approach, though that ends up requring the caller to have to specify the generic Type twice.
No, it's not possible. Constraints are defined when they are declared. In this case, the method is not generic, the class is (it's a non-generic method of a generic class). So the constraints can be only declared on the class itself.
Will this do what you want? The method will be visible to anyone, but not necessarily useable...
public class MyBaseClass<T> where T: class
{
public IQueryable<R> ShowThisMethod() where R: T, IMyInterface
{
Debug.Assert(typeof(R) == typeof(T));
// stuff.
}
}
You could define another class that inherits MyBaseClass and redefine the constraint :
public MyOtherClass<T> : MyBaseClass<T> where T : class, IMyInterface
{
public IQueryable<T> ShowThisMethod()
{
// stuff.
}
}