【问题标题】:Can I cast from an interface to a concrete type with another interface implementation我可以从一个接口转换为具有另一个接口实现的具体类型吗
【发布时间】:2012-11-23 06:58:57
【问题描述】:

首先我应该说我是一个非常喜欢接口的菜鸟,所以这可能是一个非常愚蠢的问题。如果我的标题不清楚,也很抱歉 - 符合我的心态!

我确实了解接口背后的原理,并且我想在这里使用它们来支持单元测试以及通过 DI 框架在极其混乱且无法测试的遗留代码中解耦。

我有一个名为 IDatHandler 的接口。它有一个名为 Items 的 List 属性。具体实现应该返回一个具体类型的 IDatContainer。当然有一些方法,但我把它们排除在外

public interface IDatHandler
{
    ....

   List<IDatContainer> Items
    {
        get; set;
    }

}

这是一个具体的实现:

public class ADEColorHandler : IDatHandler
    {
      ....

        public List<ADEColor> Items
        {
            get; set;

        }

    }
}

ADEColor 实现 IDatContainer。除非我将ADEColor 替换为IDatContainer,否则具体实现会失败。

有没有办法让项目以ADEColor 类型的列表形式返回,还是我只是违反了规则?

我应该说这个应用当前使用的是 NET 3.5

=========>>> 答案 - 谢谢 Charleh!

IDatHandler 接口

public interface IDatHandler<T> where T : IDatContainer
{
    ....

   List<IDatContainer> Items
    {
        get; set;
    }

}

具体类:

public class ADEColorHandler : IDatHandler<ADEColor>
        {
          ....

            public List<ADEColor> Items
            {
                get; set;

            }

        }
    }

我对 ADEColorHandler Assert 的单元测试针对此列表并通过。

【问题讨论】:

  • 我希望 ADEColorHandler 实现接口 IDatHandler 但返回一个 ADEColor 列表,而不是必须返回一个 IDatContainer 列表然后让调用者负责转换结果。我知道我可以做这样的事情,但我想知道有更好的方法。
  • 只是检查,但 List&lt;IDatContainer&gt; 应该真的是 List&lt;T&gt; - 可能只是一个错字!
  • 一切正常 - 谢谢 Charleh

标签: c# interface


【解决方案1】:

你可以走这条路:

public interface IDatHandler
{
    // Any common interface stuff
}

public interface IDatHandler<T> : IDatHandler
    where T : IDatContainer
{
    // Any generics
    List<T> Items;
}

public class ADEColorHandler : IDatHandler<ADEColor>
{
  ....

    public List<ADEColor> Items
    {
        get; set;

    }

}

这确实意味着您需要在另一端进行一些转换,因为如果您只是传递 IDatHandler 实例,您需要知道泛型类型才能查询 Items

你想达到什么目的?这可能有助于确定您可以使用什么...

或者,您可以在原始接口实现中使用 IEnumerable - 您是否需要在设计时知道集合的具体类型,还是可以摆脱强制转换?

编辑:添加上面的约束

只是想弄清楚这一点,因为使用上面的界面会在一定程度上起作用,但我的假设是你想循环通过这些来处理它们等等 - 我想知道这是否可行(需要检查)

List<IDatHandler<IDatContainer>> someList = new List<IDatHandler<IDatContainer>>();
someList.Add((IDatHandler<IDatContainer>)new ADEColorHandler());           

然后你可以枚举列表...去看看这是否有效。

编辑:不,没有工作,因为泛型类型在运行时实际上是不同的。我会搞砸的 - 我喜欢尝试找出泛型可以做什么和不能做什么!

编辑:

好吧,最好的可能是:

    public interface IDatHandler<T> : IDatHandler
        where T : IDatContainer
    {
        List<T> Items { get; set; }
    }

    public class ADEColorHandler : IDatHandler<IDatContainer>
    {
        public List<IDatContainer> Items
        {
            get;
            set;

        }
    }

这意味着你可以做到:

var items = new List<IDatHandler<IDatContainer>>();
items.Add(new ADEColorHandler());      

然后您可以从每个IDatHandler 枚举并获取Items 并查询每个IDatContainer。当然,您对具体类型是隐藏的,但我假设您在容器上有一个接口来尝试抽象这些实现细节。这应该没问题

【讨论】:

  • 至于我想要达到的目标,我想我正在努力学习....我有一堆数据文件,每个文件都是 CSV 文件并且不同。除了数据字符串的内容外,处理程序都相似。我正在尝试尽可能地通用化这个过程。
  • +1 对此答案。有没有办法在实现接口时使用协变或逆变?
  • 编辑了我认为你需要的!让我知道这是否有意义
猜你喜欢
  • 1970-01-01
  • 2021-07-22
  • 1970-01-01
  • 2019-08-31
  • 1970-01-01
  • 2022-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多