2

这是我面临的情况:

public abstract class Record { }

public abstract class TableRecord : Record { }

public abstract class LookupTableRecord : TableRecord { }

public sealed class UserRecord : LookupTableRecord { }

public abstract class DataAccessLayer<TRecord> : IDataAccessLayer<TRecord>
    where TRecord : Record, new() { }

public abstract class TableDataAccessLayer<TTableRecord> : DataAccessLayer<TTableRecord>, ITableDataAccessLayer<TTableRecord>
    where TTableRecord : TableRecord, new() { }

public abstract class LookupTableDataAccessLayer<TLookupTableRecord> : TableDataAccessLayer<TLookupTableRecord>, ILookupTableDataAccessLayer<TLookupTableRecord>
    where TLookupTableRecord : LookupTableRecord, new() { }

public sealed class UserDataAccessLayer : LookupTableDataAccessLayer<UserRecord> { }

public interface IDataAccessLayer<TRecord>
    where TRecord : Record { }

public interface ITableDataAccessLayer<TTableRecord> : IDataAccessLayer<TTableRecord>
    where TTableRecord : TableRecord { }

public interface ILookupTableDataAccessLayer<TLookupTableRecord> : ITableDataAccessLayer<TLookupTableRecord>
    where TLookupTableRecord : LookupTableRecord { }

现在,当我尝试执行以下转换时,它不会编译:

UserDataAccessLayer udal = new UserDataAccessLayer();
            ITableDataAccessLayer<TableRecord> itdal = (ITableDataAccessLayer<TableRecord>)udal;

但是,当我执行以下强制转换时,它编译时没有运行时错误:

UserDataAccessLayer udal = new UserDataAccessLayer();
            ITableDataAccessLayer<UserRecord> itdal = (ITableDataAccessLayer<UserRecord>)udal;

我真的需要使用基本ITableDataAccessLayer<TableRecord>接口,因为我不知道具体类型。

希望这是描述性的和有帮助的,足以回答我的问题。

4

3 回答 3

5

.NET 4.0 支持您尝试执行的操作,但 3.5 不支持。它被称为泛型协方差。与此同时,您可以做的是创建一个名为 ITableDataAccessLayer 的非泛型接口(在您使用 T 的任何地方使用 Object 类型)并提供显式接口实现。这是 .NET 中处理它的泛型类型的数量。

于 2009-11-22T07:46:31.727 回答
4

确实,您需要协方差。几个点。

首先,了解为什么有时这必须是非法的。以 IList 为例。假设你有一个IList<Giraffe>长颈鹿列表。你能把它转换成动物列表吗?不,不安全。是的,长颈鹿列表是动物列表,因为列表中的所有内容都是动物。但是列表是可变的;您可以将老虎放入动物列表中,但如果它确实是长颈鹿列表,那么这必须失败。由于这不安全,我们不会在 C# 4 中使 IList 协变。

其次,如果您对这个主题感兴趣,您可能想阅读我关于如何设计该功能以保持类型安全的长系列博客文章。

http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

第三,仅供参考,我将在接下来的几周内在我的博客上发布我们用来计算接口何时可以安全地协变或逆变的确切规则。

于 2009-11-22T17:06:41.537 回答
0

这会编译吗?

UserDataAccessLayer udal = new UserDataAccessLayer(); 
ITableDataAccessLayer<TTableRecord> itdal = (ITableDataAccessLayer<TTableRecord>)udal;

甚至只是

ITableDataAccessLayer<TTableRecord> itdal = new UserDataAccessLayer(); 

因为它是一个通用接口,它可能需要知道它是什么类型?

了解错误消息也会很有帮助。这通常会阐明主题。

于 2009-11-22T07:45:15.800 回答