ICollection vs ICollection<T>- ICollection<T>.Count和ICollection.Count之间的歧义

8
注意:这与另一个问题相似,但并不完全相同。
我实现了一个IBusinessCollection接口。它同时继承了ICollection<T>和旧的非泛型ICollection。我希望只使用泛型ICollection<T>,但我正在使用WPF数据绑定,并且CollectionView要求我实现旧的非泛型IList :-(
无论如何,这些接口看起来像这样:
public interface IBusinessCollection<T> : ICollection<T>, ICollection
{ }

public interface ICollection<T>
{ int Count { get; } }

public interface ICollection
{ int Count { get; } }

由于使用依赖注入,我传递了IBusinessCollection<T>类型的对象,使用它们的接口而不是具体类型,所以我的代码看起来像这样:

internal class AnonymousCollection : IBusinessCollection<string>
{ 
    public int Count { get { return 5; } }
}

public class Factory
{
    public static IBusinessCollection<string> Get()
    { return new AnonymousCollection(); }
}

当我尝试调用这段代码时,我会收到以下错误:

var counter = Factory.Get();
counter.Count; // Won't compile
// Ambiguity between 'ICollection<string>.Count' and 'ICollection.Count'

有三种方法可以使这个编译通过,但它们都不太好看。
  1. 将类转换为其具体实现(我可能不知道)
  2. 将类显式转换为ICollection
  3. 将类显式转换为ICollection<T>
是否有第四种选项,不需要我进行任何转换?我可以对IBusinessCollection<T>进行任何必要的更改。

为什么不同时显式地实现两个接口,然后直接实现公共接口呢?这仍然使得从外部“针对接口编程,而不是针对实现编程”成为可能。 - Cecil Has a Name
2个回答

14

根据我的快速测试,这似乎可以解决问题。

public interface IBusinessCollection<T> : ICollection<T>, ICollection
{
    new int Count { get;  }
}

1
PS. 没想到接口中也可以使用“new”。太好了 :-) - Orion Edwards

-1
ICollection<string> counter = Factory.Get();
counter.Count; // No longer ambiguous

我认为这并没有真正解决问题。在我的示例代码中,使用var或显式的IBusinessCollection<string>类型都会出现歧义错误。 - bobbymcr
问题要求第四个选项。他已经知道这种可能性。 - John Fisher
我仍然遇到歧义错误。 - Corbin March
1
@John:当然可以。他知道他得到的是 IBusinessObject<string> 接口,该接口实现了 ICollection<string> 接口。与普遍认为的相反,var 不是 变体!它是一个静态类型,在这种情况下在编译时解析为 IBusinessCollection<string>,该接口有两个在两个不同子接口中定义的属性,这些属性具有相同的名称。如果可能的话,使用其中之一可以消除歧义。 - Matthew Scharley
2
我不想强制转换或明确声明类型。我只想使用var并拥有干净的代码。就这方面而言,ICollection<string> counter与var counter = (ICollection<string>)相同,并不能解决问题。 - Orion Edwards
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接