给定这些基类和接口(interface)
public abstract class Statistic : Entity, IStatistic
{
protected abstract IStatisticsRepository<IStatistic> Repository {get;}
...
public class AverageCheckTime : Statistic
...
public interface IStatisticsRepository<T> : IRepository<T> where T : IStatistic
...
public interface IAverageCheckTimeRepository : IStatisticsRepository<AverageCheckTime>
...
public class AverageCheckTimeRepository : StatisticRepository<AverageCheckTime>, IAverageCheckTimeRepository
...
public class RepositoryFactory
{
public static IAverageQueueTimeRepository AverageQueueTimeRepository
{
get { return CurrentServiceLocator.GetInstance<IAverageQueueTimeRepository>(); }
}
为什么 AverageCheckTime 的实现会抛出一个无效的转换异常:
protected override IStatisticsRepository<IStatistic> Repository
{
get { return (IStatisticsRepository<IStatistic>)RepositoryFactory.AverageCheckTimeRepository; }
}
如何转换 IAverageCheckTimeRepository
的实例作为IStatisticsRepository<IStatistic>
我以为它已经是?
好的,我已经做了这些改变......这让我想知道我是否已经在一开始就使用泛型
public interface IStatisticsHelper
{
void GenerateStatistics();
List<IStatistic> BuildReport();
}
...
public interface IStatisticsRepository<T> : IRepository<T>, IStatisticsHelper where T : IStatistic
{
}
...
public abstract class Statistic : Entity, IStatistic
{
protected abstract IStatisticsHelper Repository { get; }
...
public class AverageCheckTime : Statistic
{
protected override IStatisticsHelper Repository
{
get { return RepositoryFactory.AverageCheckTimeRepository; }
}
最佳答案
不,C# 3 不支持generic variance。 C# 4 可以,但您必须声明 IStatisticsRepository
在 T
中是协变的:
public interface IStatististicsRepository<out T> : IRepository<T>
where T : IStastistic
变体通常不安全 - 这取决于泛型类型参数的使用方式。 C# 4 支持作为引用类型的类型参数的协变和逆变,但仅当涉及的泛型类型是接口(interface)或委托(delegate)时,并且仅当类型参数在接口(interface)/委托(delegate)中以适当的方式使用时。
没有看到 IRepository<T>
的声明,我们无法判断它是否安全。例如,如果 IRepository<T>
包含这样的方法:
void Save(string id, T value);
那么它不会是安全的,因为你可以这样写:
IStatisticsRepository<IStatistic> repo = RepositoryFactory.AverageCheckTimeRepository;
IStatistic foo = new SomeOtherStastisticType();
repo.Save("Foo", foo);
那会试图保存 SomeOtherStatisticType
AverageCheckTimeRepository
中的值,这违反了类型安全。在 T
中使接口(interface)协变是唯一安全的如果类型为 T
的值只能从界面“出来”。 (请注意,这到底是什么意思有些皱纹......)
有关这方面的更多信息,请参阅 Eric Lippert 的 blog series on the topic .
关于c# 3.0 转换接口(interface)泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7600345/