c# 3.0 转换接口(interface)泛型类型

标签 c# generics casting c#-3.0

给定这些基类和接口(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 可以,但您必须声明 IStatisticsRepositoryT 中是协变的:

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/

相关文章:

方法参数的 C# null 条件简写

c# - .NET - 使用 GifBitmapEncoder 创建循环 .gif

function - 将 scala 代码概括为函数

c++ - 使用 static_cast<> 对指针进行类型转换

c++ - 将基对象返回到向上转换的派生类的最合适方法是什么?

c# - 在 Windows 窗体应用程序上使用的最佳 Web 浏览器控件是什么?

c# - 在 dll 库中显示消息框

c# - 如何在 C# 中查找通用控件的标记

c# - 访问函数内泛型类型的属性

java - 创建类的泛型类型数组