C# 具有非泛型方法约束的泛型类?
我将此类用作我的存储库:C# 具有非泛型方法约束的泛型类?,c#,generics,type-constraints,C#,Generics,Type Constraints,我将此类用作我的存储库: public class Repository<T> where T : class, new() { public T GetByID(int id) { //Code... } } 由于new()约束,这使得存储库模板类无效。 我想做这样的东西: public class Person { public CPersonID PersonID { get; private set; }
public class Repository<T> where T : class, new()
{
public T GetByID(int id)
{
//Code...
}
}
由于new()
约束,这使得存储库模板类无效。
我想做这样的东西:
public class Person
{
public CPersonID PersonID { get; private set; }
//This shouldn't exist outside Person, and only Person knows the rules how to handle this
public class CPersonID
{
internal CPersonID() { }
}
}
public class Repository<T> where T : class
{
//This function should be created only when the T has new()
public GetByID(int id) where T : new()
{
}
//And this could be the alternative if it doesn't have new()
public GetByID(T element, int id)
{
}
}
不,你不能这样做 必须在引入泛型参数的位置指定所有约束,在本例中是在类级别 因此,您有两种选择:
,new()
作为约束,将存储库类的使用限制为使用具有公共无参数构造函数的类型您无法要求编译器创建一个能够调用特定方法的类,即“仅当类型具有构造函数时才允许我调用GetByID”。不,您不能这样做 必须在引入泛型参数的位置指定所有约束,在本例中是在类级别 因此,您有两种选择:
,new()
作为约束,将存储库类的使用限制为使用具有公共无参数构造函数的类型您无法要求编译器创建一个能够调用特定方法的有条件类,即“如果类型具有构造函数,则仅允许我调用GetByID”。正如Lasse V.Karlsen已经回答的那样,这是不可能的。然而,你可以非常接近,非常接近实际用途 给定T:class所在的
公共类存储库,您无法定义仅当T
具有无参数构造函数时才存在的实例方法。你不需要那个。您只需要repository.GetByID(3)
即可工作。如果GetByID
是一个实例方法,但如果它是一个扩展方法,并且扩展方法可以向T
添加需求,那么这种方法就可以工作
public static class RepositoryExtensions
{
public T GetByID(this Repository<T> repo, int id) where T : class, new()
{
...
}
}
正如Lasse V.Karlsen已经回答的那样,这是不可能的。然而,你可以非常接近,非常接近实际用途
给定T:class
所在的公共类存储库,您无法定义仅当T
具有无参数构造函数时才存在的实例方法。你不需要那个。您只需要repository.GetByID(3)
即可工作。如果GetByID
是一个实例方法,但如果它是一个扩展方法,并且扩展方法可以向T
添加需求,那么这种方法就可以工作
public static class RepositoryExtensions
{
public T GetByID(this Repository<T> repo, int id) where T : class, new()
{
...
}
}
如果希望将其作为编译时约束,可以这样做
public class Class<T> where T : class
{
public void Method<U> where U : T, new()
{
// ...
}
}
公共类,其中T:class
{
公共无效方法,其中U:T,new()
{
// ...
}
}
但这也有你不得不做的缺点
new Class<HasConstructor>().Method<HasConstructor>();
newclass().Method();
因为类型不会被隐式拾取。优点是不会编译以下内容:
new Class<NoConstructor>().Method<NoConstructor>();
newclass().Method();
如果希望将其作为编译时约束,可以这样做
public class Class<T> where T : class
{
public void Method<U> where U : T, new()
{
// ...
}
}
公共类,其中T:class
{
公共无效方法,其中U:T,new()
{
// ...
}
}
但这也有你不得不做的缺点
new Class<HasConstructor>().Method<HasConstructor>();
newclass().Method();
因为类型不会被隐式拾取。优点是不会编译以下内容:
new Class<NoConstructor>().Method<NoConstructor>();
newclass().Method();
Repository
为什么需要有new()
约束?@dav_i因为GetByID
和其他类似的Get
方法,我创建了一个T的新实例,填充它的数据,然后返回它。你无法按照你想要的方式实现这一点,但是,您也可以使用类似AutoMapper的库,并允许存储库的实现确定如何将存储库中的原始数据转换为要传递给自动映射器的数据传输对象。为什么repository
需要new()
constraint at all?@dav_i由于GetByID
和其他类似的Get
方法,我创建了一个新的T实例,填充它的数据,然后返回它。你不能用你想要的方式实现它,但是,您也可以使用类似AutoMapper的库,并允许存储库的实现确定如何将存储库中的原始数据转换为要传递给auto mapper的数据传输对象。