【问题标题】:Interface Polymorphism in C# 2.0C# 2.0 中的接口多态性
【发布时间】:2011-09-24 10:49:54
【问题描述】:

假设我有这个接口:

public interface IFoo
{
   string Text {get;}
}

以及实现它的这个类:

public class Bar : IFoo
{
   public string Text
   {
      get {return "Hello World!";}
   }
}

我有一个以List<IFoo> 为参数的函数。当我尝试将 List<Bar> 传递给它时,我得到了这个编译器错误:

Argument 1: cannot convert from System.Collections.Generic.List<Bar>
to System.Collections.Generic.List<IFoo>

这是为什么?看起来这应该是出于同样的原因,就好像我直接传递了一个继承自 Bar 的类的列表一样。

【问题讨论】:

  • 尝试使用泛型。然后,您的函数可以将 List 作为参数。查看msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx 向下滚动大约一半到通用方法
  • 我需要传递的对象来实现这个接口。如果我使用的是较新版本的 .NET,我会很乐意使用泛型并使用 Func 参数从我传递的对象中获取我需要的信息。
  • 根据文章我链接的泛型应该在 .net 2.0 中工作
  • 可以使用Frob(List&lt;T&gt; list) where T : IFoo

标签: c# .net oop interface .net-2.0


【解决方案1】:

这是为什么?看起来这应该与我传递一个直接从 Bar 继承的类的列表相同的原因。

因为这种灾难可能发生:

class EvilBar : IFoo { }

List<Bar> list = new List<Bar>();
List<IFoo> foos = list; // suppose it were allowed
foos.Add(new EvilBar());

现在您已将EvilBar 添加到列表中,而只能接受Bar。糟糕!

基本上,您已经发现T -&gt; List&lt;T&gt;T 中不是协变的。

【讨论】:

  • 这似乎不是问题。编译器允许从List&lt;Bar&gt; 转换为List&lt;IFoo&gt;,因为Bar 实现了IFoo。出于同样的原因,它应该允许将EvilBar 添加到实现IFoo 的对象列表中。但是,它不应该允许从 List&lt;IFoo&gt; 回滚到 List&lt;Bar
  • 这在 .NET 的更高版本中是否有所改变?
  • @linepogl:你在说什么? IFoo foo = new EvilBar(); 非常好。你投了反对票吗?
  • @linepogl:这不是直接的类比。您不能将EvilBar 添加到List&lt;Bar&gt;,这就是为什么我的示例是一场灾难。
  • @linepogl 我认为您缺少的是 listfoos 仍然是同一个列表。例如,当您使用 .NET 3.5 扩展方法 Cast&lt;T&gt; 时,它会创建一个新列表,在这种情况下,可以向 List&lt;IFoo&gt; 添加任何内容,但在这种情况下,由于它们都是同一个列表,因此添加 @987654341 @ to foos 表面上看起来不错,但实际上仍然是List&lt;Bar&gt; 这并不好。
【解决方案2】:

因为 .Net 2.0 不支持泛型逆变。不过,您可以使用数组来做到这一点。

IFoo[] foos = new Bar[5];

另一种选择是做

List<IFoo> myList = myBarList.ConvertAll(b => (IFoo)b);

【讨论】:

  • 由于我的回答中概述的原因,这种协方差被破坏了。
  • 我将我的参数转换为数组,在传递的参数末尾添加.ToArray(),编译器很高兴。
  • @Mr.杰斐逊:不安全!
  • @Mr. Jefferson:是的,您可能会遇到运行时错误。 blogs.msdn.com/b/ericlippert/archive/2007/10/17/…
【解决方案3】:

不要传递List&lt;Bar&gt;。使用 cast 并传递这个:

yourObj.YourMethod(yourListOfBar.Cast<IBar>().ToList());

【讨论】:

  • 我认为您的 Cast 方法在 .NET 2.0 中不存在。否则效果会很好。
猜你喜欢
  • 1970-01-01
  • 2012-06-25
  • 2016-09-12
  • 2013-05-17
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
  • 2020-11-23
相关资源
最近更新 更多