This question already has answers here:
What does new() mean?
(3 answers)
Closed 6 years ago.
I have an Abstract class that is implemented like this:
public abstract class BaseImplementation<T, U> : IHistory<T>
where T : class, IEntity, new()
where U : DbContext, new()
I understand that the generic argument <U> is an EF DbContext.
I understand that the generic argument <T> must be a class that implements the IEntity Interface.
What is the "new()"? Must be a new instance of a given class? What is the purpose of that?
Note that is declared in both <T> and <U>
Thank you.
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."
I don't really have much more to add to this as I think the explanation above is sufficient.
The new() is called a new constraint and it requires that the type argument has a public, parameterless constructor.
The benefit of using it is that you can create an instance of your generic type inside the class, without explicitly knowing the type passed in.
For example:
public PersonEntity : IEntity
{
// public parameterless constructor
public PersonEntity()
{
}
}
public abstract class BaseImplementation<T, U> : IHistory<T>
where T : class, IEntity, new()
where U : DbContext, new()
{
public T CreateEntity()
{
var entity = new T();
// entity will be the type passed to `T` when instantiating `BaseImplementation`
}
}
Then usage would be something like:
public class PersonImpl : BaseImplementation<PersonEntity, DataContext>
{
public void Method1()
{
var entity = CreateEntity();
// entity is typeof(PersonEntity);
}
}
new() is a constraint specifying that the type argument must have a public parameterless constructor. For more information about the generic type constraint, see MSDN。
Related
This question already has answers here:
Pass An Instantiated System.Type as a Type Parameter for a Generic Class
(6 answers)
Closed 5 days ago.
I'm wanting to do a generic scoped.
I have a class where it needs to receive a "T" type to instantiate it. My problem is receiving this type "T" otherwise without being explicit.
example:
public class MyClass<T> : IMyInterface<T> where T : class {}
public interface IMyInterface<T> where T : class {}
public void test()
{
Type xx = new someClass1().GetType();
Type tt = new someClass2().GetType();
Type yy = new someClass3().GetType();
services.AddScoped<IMyInterface<xx>, MyClass<xx>>();
services.AddScoped<IMyInterface<tt>, MyClass<tt>>();
services.AddScoped<IMyInterface<yy>, MyClass<yy>>();
}
Another example
public void test()
{
foreach (Type item in someClass.ToList())
{
services.AddScoped<IMyInterface<item>, MyClass<item>>();
}
}
This allows the MyMethod method to create an instance of T using the new operator. Note that this approach requires that the type parameter T be constrained in some way in order to be used without being explicitly specified.
public void MyMethod<T>() where T : new()
{
T instance = new T();
// code
}
In C#, I've define an Interface like following:
public interface IClassA
{
IEnumerable<T> Search<T>()
where T : new();
}
and
public interface IClassB
{
...
}
If I do
public DoSomething(IClassA a)
{
// Error: IClassB must be a non-abstract type with a public parameterless constructor.
var result = a.Search<IClassB>();
}
How can I fix this so that I can pass IClassB as generic type in IClassA.Search? or this is impossible?
You added constraint new() to your method, which means, that a type argument in a generic method declaration must have a public parameterless constructor. Interface can't have constructors. Remove where T: new() constraint.
This question already has answers here:
How to correctly cast a class to an abstract class when using type generics?
(4 answers)
Closed 4 years ago.
Casting Deriving Class as Base Class
I have a base abstract class which is generic and inherits from IComparable which is defined like below
public abstract class BaseClass<T> where T : IComparable
{
protected readonly T Data;
protected BaseClass(T data)
{
Data = data;
}
public abstract T Get();
}
Then I have defined a classe which inherits from this base class and has a specific generic type and is defined like below:
public class Name : BaseClass<String>
{
public Name(string data) : base(data)
{
}
public override string Get()
{
throw new NotImplementedException();
}
}
As generic type is string and string inherits from IComparable, I expect to be able to define new Name object with string value as generic type, but I get casting error for defining Name object like this:
BaseClass<IComparable> obj;
obj = new Name("behro0z");
and the error is
Error CS0029 Cannot implicitly convert type ConsoleApplication1.Name
to
ConsoleApplication1.BaseClass<System.IComparable> ConsoleApplication1
You're declaring a variable of type BaseClass<T>, and substitute T with IComparable.
That's valid, but that's not what your Name class is. That one derives from BaseClass<string>, not BaseClass<IComparable>, even though string implements IComparable.
You can either declare your variable obj to be of type BaseClass<string>, or the more derived type, Name.
Read up on covariance, C# Generics Inheritance Problem.
I'm trying to create a generic controller on my C#/MVC/Entity Framework application.
public class GenericRecordController<T> : Controller
{
private DbSet<T> Table;
// ...
public action()
{
// ...
db.Entry(T_Instance).State = System.Data.Entity.EntityState.Modified;
}
}
However the DbSet<T> and T_Instance line has a compiler error.
The type T must be a reference type in order to use it as parameter.
When I constrain it as a class, it was solved.
Controller where T : class
What does the error mean? I'm not asking for a solution, I would like to understand why this error occurs and why constraining it as a class solves it.
If you look at the definition of DbSet<TEntity>:
public class DbSet<TEntity> : DbQuery<TEntity>, IDbSet<TEntity>, IQueryable<TEntity>, IEnumerable<TEntity>, IQueryable, IEnumerable, IInternalSetAdapter
where TEntity : class
Because it has a type constraint that the generic type must be a class then you must initialize it with a type that also matches this condition:
public class GenericRecordController<T> : Controller where T : class
{ ... }
They apparently have a constraint on the generic type.
All you need to change is:
public class GenericRecordController<T> : Controller where T : class
This tells the compiler that only reference types may be supplied as a type for T.
You can do it on just a method as well:
public bool HasKey<T>(T obj) where T : class
{
return _db.Entry<T>(obj).IsKeySet;
}
I am new to C# and I am faced with a class with this structure:
public class SimpleGetter<TSubs> : GetterBase<TSubs>, ISubscriptionsSingleGetter<TSubs>
where TSubs : class, ISimpleSubscription, new()
{
UserSubscriptionsResponse<TSubs> ISubscriptionsSingleGetter<TSubs>.Get()
{
return ((ISubscriptionsSingleGetter<TSubs>)this).Get(null);
}
UserSubscriptionsResponse<TSubs> ISubscriptionsSingleGetter<TSubs>.Get(string userId)
{
return GetSubsResponse(userId);
}
}
I need to pass userID to the get() function (if possible), but I am confused on how to do that. I have tried to do some research on this but I do not even know what this way of defining a class is called. I come from objective c where things seem more straight forward.
I do not even know what this way of defining a class is called
This is a generic class.
public class SimpleGetter<TSubs> : GetterBase<TSubs>, ISubscriptionsSingleGetter<TSubs>
where TSubs : class, ISimpleSubscription, new()
which has one generic type parameter TSubs. This class inherits the GetterBase<TSubs> and implements the interface ISubscriptionsSingleGetter<TSubs>. Furthermore, the TSubs must be a reference type and must have a parameterless constructor, which implements the ISimpleSubscription interface.
public class FakeSubs : ISimpleSubscription
{
public FakeSubs()
{
}
// Here you have to implement ISimpleSubscription.
// You could also define any properties, methods etc.
}
// Now you could use your generic class as below:
var simpleGetter = new SimpleGetter<FakeSubs>();
Having created the above instance, you can call the Get method as Tewr, pointed out in his comment:
var response = ((ISubscriptionsSingleGetter<FakeSubs>)simpleGetter).Get(42);
Just to complement Christos' answer and help you understand the syntax a bit better, let's break the class definition term by term.
public - visible to all callers.
class - a reference type (i.e. not a struct).
SimpleGetter<TSubs> - the class name is SimpleGetter, and it is generic with respect to the parameter TSubs.
: GetterBase<TSubs> - it inherits from a base class which is itself generic with respect to the parameter TSubs.
, ISubscriptionsSingleGetter<TSubs> - and it also implements the generic interface ISubscriptionSingleGetter.
where TSubs: - there are some constraints on the type which the generic parameter TSubs must be of.
class - it must itself also be a reference type.
ISimpleSubscription - it must implement this (non-generic) interface.
new() - it must have a public parameterless constructor.