这是我面临的情景:
public abstract class Record { }
public abstract class TableRecord : Record { }
public abstract class LookupTableRecord : TableRecord { }
public sealed class UserRecord : LookupTableRecord { }
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 { }
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> { }
现在,当我尝试将UserDataAccessLayer转换为它的通用基类型 ITableDataAccessLayer<TableRecord>
时,编译器会抱怨它无法隐式转换类型 .
当我尝试在通用参数的接口声明中使用 in
或 out
关键字时,编译器会抱怨 Invalid variance: The type parameter must be invariantly valid.
我有以下抽象类:
public abstract class FileProcessor : IDisposable
{
protected abstract ITableDataAccessLayer<TableRecord> CreateTableDataAccessLayer();
}
以及具体实施示例如下:
public class UserFileProcessor : FileProcessor
{
protected override ITableDataAccessLayer<TableRecord> CreateTableDataAccessLayer()
{
return new UserDataAccessLayer();
}
}
return new UserDataAccessLayer(); is where the compiler is complaining.
2 回答
据我所知,如果要使用协方差,则需要为接口指定out关键字 .
http://geekswithblogs.net/NewThingsILearned/archive/2009/09/30/covariance-in-.net-4.0.aspx
共同和反差的问题在于它对所涉及的类型施加了相当多的限制,因此它可能并不适用于所有情况 .
我设法通过进行以下更改来编译代码:
注意:
为IDataAccessLayer和ITableDataAccessLayer添加了
但是,这意味着您不仅限于在这些类型的输出位置使用TTableRecord,这意味着:
类型用于只读属性(不适用于可写属性)
方法的返回类型
out方法的参数类型
你不能用它来:
可写属性
ref或非out / ref参数的方法
很可能,没有办法让co-contra和contra-variance帮助你 .