使用不同的泛型参数实现相同的泛型接口2次

本文关键字:泛型接口 2次 实现 泛型 参数 | 更新日期: 2023-09-27 18:10:18

我必须使用不同的泛型参数同时实现2个接口,如下所示。我已经很困惑了。我不知道它们中的哪一个在foreach中迭代自己。现在我明白了第一个是隐式选择。

我已经尝试过new BarList().GetEnumerator(),但我无法在方法级别指定类型参数。

我找到的唯一解决方案是将其转换为(new BarList() as IEnumerable<string>)接口

在困惑够了之后。我只是想知道这个设计是不是真的很好?我必须避免再次实现相同的通用接口?

class Program
{
    static void Main(string[] args)
    {
        foreach (var item in new BarList())
        {
        }
    }
}
class BarList: IEnumerable<string>, IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        throw new NotImplementedException();
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
    IEnumerator<string> IEnumerable<string>.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}
编辑:

让我解释一下为什么我要这样走。

我必须实现从IList<T>继承的IPagedList<T>接口。我想写一个扩展方法把它转换成我的视图模型。像下面的

GetAll().ToPagedList(pageindex);//这是返回IPagedList然后我想使用它像下面;

GetAll().ToPagedList(pageindex).ToViewModel<T,TViewModel>();

为了实现这一点,我试图通过扩展方法返回IPagedList<ViewModel>。在这种情况下,我必须实现IPagedList 2次不同的参数。但这种策略使事情变得令人困惑。

使用不同的泛型参数实现相同的泛型接口2次

这似乎有点令人困惑。为什么不通过将枚举数添加为属性而不是在类上实现它们来显式地显示正在发生的事情呢?例如,

class ProductCollection 
{
   public IEnumerable<int> EnumerateTheInts { get { //code to produce enumerator }}
   public IEnumerable<string> EnumerateTheStringss { get { //code to produce enumerator }}
}

在一个对象上两次实现一个开放的泛型接口并不总是坏事。例如,IHandle可以由一个可以处理两种类型t的类来实现。然而,我发现实现IEnumerable两次会让人感到困惑,因为你可能不会枚举你在For -each或LINQ中期望的类型。顺便说一下,实现多个索引器的原因也是一样的。索引器的类型将决定你的结果,我可以证明这是非常令人困惑的!

编译器按照c#语言规范8.8.4中的规则选择IEnumerator<int> GetEnumerator方法,首先在BarList类型上查找可访问的GetEnumerator()方法。其中唯一可用的是返回IEnumerator<int>的那个。

如果您让方法也使用显式接口实现,那么它将进入第8.8.4节的后期阶段,该节指出,如果存在多个类型T,从而存在从表达式类型(此处为BarList)到IEnumerable<T>的隐式转换,则会产生错误。

我想说这个一个令人困惑的设计-我可能会添加属性或方法来检索适当的"视图"的数据

我会避免。然而,这取决于你的用法。

如果您只是想将实例传递给显式需要IEnumerable<string>参数的函数,则可以:

  • 你不需要转换
  • 函数甚至不会"看到"实现的其他接口,所以没有任何混乱。

YMMV

您当前的设计令人困惑。虽然您没有提供关于集合本身性质的任何信息,但从名称来看,我可以假设您应该迭代一堆产品。也许,您应该简单地有一个类型为Product的类,具有string属性和int属性,并简单地返回IEnumerable<Product>

通过这种方式,使用LINQ扩展方法,您可以使用:

组合您真正想要的IEnumerable<T>对象:
collection.Select(product => product.IntegerProperty)
collection.Select(product => product.StringProperty)

当然,您也可以在对象内部提供辅助方法:

class ProductCollection : IEnumerable<Product> {
    public IEnumerable<Product> GetEnumerator() {
       // ... return Product objects here.
    }
    public IEnumerable<int> AsIntegerCollection() {
       // yield the integer collection here
    }
    public IEnumerable<string> AsStringCollection() {
       // yield the string collection here
    }
}

string和int类型的集合是什么?我想它们的意思是与产品相关的东西(例如名称,Id等),所以我宁愿这样做:

class ProductCollection : IEnumerable<Product>
{
    public IEnumerator<Product> GetEnumerator()
    {
       ...
    }
    public IEnumerator<string> ProductNames // a helper to enumerate product names
    {
       ...
    }
    public IEnumerator<int> ProductIds // a helper to enumerate product ids
    {
       ...
    }
}