使用不同的Generic参数实现相同的通用接口2次

时间:2011-10-04 10:20:33

标签: c# .net

我必须使用不同的通用参数同时实现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();
    }
}

修改

让我解释为什么我会这样做。

我必须实现继承自IPagedList<T>的{​​{1}}接口。我想编写扩展方法,将其转换为我的视图模型。如下所示

IList<T>; //返回IPagedList然后我想像下面那样使用它;

GetAll().ToPagedList(pageindex)

为了实现这一点,我尝试通过该扩展方法返回GetAll().ToPagedList(pageindex).ToViewModel<T,TViewModel>(); 。在这种情况下,我必须使用不同的参数实现IPagedList 2次。但这种策略令人困惑。这就是它的原因。

5 个答案:

答案 0 :(得分: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中所期望的类型。顺便实现多个索引器的相同原因。索引器的类型将决定你的结果,我可以证明这是非常令人困惑的!

答案 1 :(得分:2)

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

如果你已经那个方法也使用了显式接口实现,那么它将进入第8.8.4节的后面阶段,它说明如果有多个类型T这样从表达式类型(此处为IEnumerator<int>)到BarList进行隐式转换,然后产生错误。

我会说这个一个令人困惑的设计 - 我可能会添加属性或方法来检索数据上的相应“视图”。

答案 2 :(得分:1)

我会避免它。但是,这取决于您的使用情况。

如果你只想将实例传递给一个明确要求IEnumerable<string>参数的函数,那就没关系了:

  • 你不需要施展
  • 该功能甚至不会'看到'实现的其他接口,所以没有任何混淆。

YMMV

答案 3 :(得分:1)

您当前的设计令人困惑。虽然您没有提供有关集合本身性质的任何信息,但从名称来看,我可以假设您应该迭代一堆产品。也许,您应该只拥有一个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
    }
}

答案 4 :(得分:1)

这些字符串和整数的集合是什么?我想它们意味着与产品有关的东西(例如Name,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
    {
       ...
    }
}