.NET 4.0 通用不变式、协变式、逆变式
这是我面临的场景:
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
时,编译器抱怨它无法隐式转换类型。
当我尝试在泛型参数的接口声明中使用 in
或 out
关键字时,编译器会抱怨无效方差:类型参数必须始终有效
我有以下抽象类:
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();这是编译器抱怨的地方。
Here's the scenario i am faced with:
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> { }
Now when i try to cast UserDataAccessLayer to it's generic base type ITableDataAccessLayer<TableRecord>
, the compiler complains that it cannot implicitly convert the type.
When i try and use the in
or out
keywords in the interface declaration for the generic parameters, the compiler complains about Invalid variance: The type parameter must be invariantly valid.
I have the following abstract class:
public abstract class FileProcessor : IDisposable
{
protected abstract ITableDataAccessLayer<TableRecord> CreateTableDataAccessLayer();
}
And a sample concrete implementation as follows:
public class UserFileProcessor : FileProcessor
{
protected override ITableDataAccessLayer<TableRecord> CreateTableDataAccessLayer()
{
return new UserDataAccessLayer();
}
}
return new UserDataAccessLayer(); is where the compiler is complaining.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
协变和逆变的问题在于,它对所涉及的类型施加了相当多的限制,因此它可能并不适用于所有情况。
我设法通过进行以下更改来编译您的代码:
注意:
但是,这意味着您不限于仅在这些类型的输出位置中使用 TTableRecord,这意味着:
您不能将其用于:
因此,很可能没有办法让协方差和逆变函数在这里为您提供帮助。
The problem with co- and contra-variance is that it imposes quite a bit of restrictions on the types involved, so it might not be applicable in all cases.
I managed to get your code to compile by making the following changes:
Note:
This, however, means you're not restricted to using TTableRecord only in output positions in those types, which means:
You can not use it for:
So likely, there is no way to make co- and contra-variance help you here.
据我所知,如果要使用协方差,则需要为接口指定 out 关键字。
链接
As far as I know you need to specify the out keyword for the interface if you want to use covariance.
Link