Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有非泛型方法约束的泛型类?_C#_Generics_Type Constraints - Fatal编程技术网

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()
    作为约束,将存储库类的使用限制为使用具有公共无参数构造函数的类型
  • 不要将其添加为约束,并在运行时使用反射来尝试构造对象
  • 请注意,如果类型没有有效的构造函数,则第2点可能会失败(在运行时)


    您无法要求编译器创建一个能够调用特定方法的类,即“仅当类型具有构造函数时才允许我调用GetByID”。

    不,您不能这样做

    必须在引入泛型参数的位置指定所有约束,在本例中是在类级别

    因此,您有两种选择:

  • 添加
    ,new()
    作为约束,将存储库类的使用限制为使用具有公共无参数构造函数的类型
  • 不要将其添加为约束,并在运行时使用反射来尝试构造对象
  • 请注意,如果类型没有有效的构造函数,则第2点可能会失败(在运行时)


    您无法要求编译器创建一个能够调用特定方法的有条件类,即“如果类型具有构造函数,则仅允许我调用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的数据传输对象。