用于声明抽象泛型类型变量的C#语法

时间:2009-05-04 22:08:31

标签: c# generics abstract-class

我的课程定义如下;

public abstract class Repository<TEntity, TDataContext> : DisposableBaseClass
   where TEntity : class
   where TDataContext : DataContext, new()
{...contains Linq to SQL related functionality

在具体的子类中,我将类型定义为;

public class ConcreteRepo : Repository<LSTableClass, LSDataContext>

在下一层,我有业务对象,它将Repository对象保存为私有变量。

这很好;

private ConcreteRepo _repository;

然而,我然后将其重构为所有业务对象的父类 - 这个父类保存存储库/实现Dispose模式以处置存储库等。

我的问题是我无法获得声明变量的语法。

我最接近的是;

protected Repository<Object, DataContext> _repository;

但这会产生编译错误:

“错误1'System.Data.Linq.DataContext'必须是具有公共无参数构造函数的非抽象类型,才能在泛型类型或方法中将其用作参数'TDataContext'... .Repository” ...“

我尝试了其他各种方法,但遇到了其他问题。

在继承此抽象类的业务层对象中,我正在创建并使用带有强制转换的_repository变量;

(Repository<LSTableClass, LSDataContext>)_repository = new ConcreteRepo();
  • 我觉得这很好,假设我可以在父母那里得到这个声明。

如果我无法使用它,我必须使用完整/具体类型的详细信息在每个业务对象中声明_repository,并在每个业务对象中实现dispose模式以清除。不是世界末日,但我不想这样做。

2 个答案:

答案 0 :(得分:3)

如果我正确理解您的问题,您需要添加第三个通用参数,即存储库类型,它被约束为具有适当参数类型的Repository的后代。

再概述一下:

public abstract class Repository<TEntity,TDataContext>
    where TEntity : class
    where TDataContext : DataContext, new() {}

public abstract class BusinessObject<TEntity,TDataContext,TRepository>
    where TEntity : class
    where TDataContext : DataContext, new()
    where TRepository : Repository<TEntity,TDataContext>
{
    TRepository _repository;
}

public class ConcreteObject : BusinessObject<LSTableClass,LSDataContext,ConcreteRepo>
{ // ...

我知道它可能没有你想要的那么紧凑,但是为了有效地减少这个但仍然保留强类型需要的是高阶泛型类型(在Haskell中称为类型类):一种指示类型参数的方法它们本身是通用的,可以采用类型参数。

答案 1 :(得分:3)

您的声明

protected Repository<Object, DataContext> _repository;

由于你对它施加的限制而无效:

...    
where TDataContext : DataContext, new()

特别是new()部分。

我猜你想要“注入”满足你的通用界面的对象。

两件事:

  • 您无法在Repository<Object, DataContext>Repository<LSTableClass, LSDataContext>之间进行转换。不是C#3。这称为反演/协方差,在C#4之前不可用。在C#3中,这两种是完全不同的类型。

  • 如果要将泛型成员存储在类中,则类型参数必须是具体类型,或者必须在父类声明中声明为类型参数(使 < / strong>通用)。

选项:

  • 在父类上使用泛型类型参数。
  • 从类声明中删除new()约束。