【问题标题】:C# syntax for declaring a variable of an abstract generic type用于声明抽象泛型类型变量的 C# 语法
【发布时间】:2010-10-23 18:24:30
【问题描述】:

我有一个类定义如下;

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>

在下一层,我有将存储库对象作为私有变量保存的业务对象。

这很好;

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 模式以进行清理。不是世界末日,但我不想这样做。

【问题讨论】:

  • 所以我理解正确的是“private ConcreteRepo _repository;”在你重构的类中吗?您希望您正在编写的类包含此存储库字段 AND 是存储库的 TEntity 类型参数吗?你重构的具体内容对我来说不是很清楚。

标签: c# generics abstract-class


【解决方案1】:

如果我正确理解您的问题,您需要添加第三个通用参数,即存储库类型,它被限制为具有适当参数类型的 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 中称为类型类):一种指示类型参数的方法本身是泛型的,并且可以接受类型参数。

【讨论】:

  • 谢谢巴里,这正是我需要的,现在一切正常,非常感谢
【解决方案2】:

你的声明

protected Repository<Object, DataContext> _repository;

由于您对其施加的限制而无法正常工作:

...    
where TDataContext : DataContext, new()

特别是new() 部分。

我猜你想“注入”一个满足你的通用接口的对象。

两件事:

  • 您无法在 Repository&lt;Object, DataContext&gt;Repository&lt;LSTableClass, LSDataContext&gt; 之间进行转换。不适用于 C# 3。这称为逆变/协变,直到 C# 4 才可用。在 C# 3 中,这是两种完全不同的类型。

  • 如果你想在一个类中存储一个泛型成员,那么类型参数要么必须是具体类型,要么必须在父类声明中声明为类型参数(使得 that 通用)。

选项:

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

【讨论】:

  • 感谢马特的回答;不幸的是,我似乎只能将一个答案标记为正确答案,否则我也会标记你的。当您放置它们时,我选择了第一个选项,因为您的猜测是正确的,我需要注入一个对象,因此需要保留 new() 约束。再次感谢您的回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 2012-07-23
  • 2011-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多