C#3.0铸造的接口泛型类型

问题描述:

鉴于这些基类和接口C#3.0铸造的接口泛型类型

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>我认为它已经是?


OK,我做了这些改变......这使我想知道如果我已经在上面与仿制药摆在首位

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; } 
    } 
+0

你失去了一些东西,因为没有在那里我看到了'StatisticRepository '是'IStatisticRepository ' – msarchet

+0

作出编辑:公共接口IStatisticsRepository :IRepository 其中T:IStatistic –

+0

@BobTodd:现在我们不'不知道'IRepository '看起来像...... –

不,C#3不支持通用方差。 C#4,但你必须声明IStatisticsRepository是协变的T

public interface IStatististicsRepository<out T> : IRepository<T> 
    where T : IStastistic 

差异不是一般安全- 这取决于泛型类型参数是如何使用的。只有当涉及的泛型类型是接口或委托,并且只有在接口/委托中以适当的方式使用类型参数时,C#4才支持引用类型的类型参数的协方差和反变量。

没有看到IRepository<T>的声明,我们无法判断它是否安全。例如,如果IRepository<T>包含这样的方法:

void Save(string id, T value); 

那么不会是安全的,因为你可以写:

IStatisticsRepository<IStatistic> repo = RepositoryFactory.AverageCheckTimeRepository; 
IStatistic foo = new SomeOtherStastisticType(); 
repo.Save("Foo", foo); 

,这将是试图拯救AverageCheckTimeRepository中的SomeOtherStatisticType值,这违反了类型安全性。如果T类型的值仅出现在接口“出”,那么仅在T中使接口协变才是安全的。 (有一些皱纹正是这意味着什么,请记住你......)

欲了解更多信息,请参阅Eric Lippert的blog series on the topic