关于c#:我很难切换我的IEnumerable< T>

I'm having difficulty switching my IEnumerable<T> implementation to ICollection<T>

这让我很疯狂,所以我想我应该把它扔到社区里,而不是头撞在桌子上。

我正在将应用程序的某个区域从使用IEnumerable切换到ICollection。我在IEnumerableOfInterfaceExtensions中定义了几个扩展方法,我希望将这些方法转换为ICollectionFiInterfaceExtensions,在我将所有内容从封面下切换出去之后,但在我的存储库中切换出集合时,会出现(意外)错误:

1
System.Collections.Generic.ICollection<T>' does not contain a definition for 'Bar' and the best extension method overload 'Application.Data.Repositories.RepositoryExtensions.Bar(System.Collections.Generic.ICollection<Application.Domain.Models.IInterface>, System.Collections.Generic.IEnumerable<Application.Domain.Models.IInterface>)' has some invalid arguments

这只在我尝试使用ICollection而不是IEnumerable时才会出现。我的IEnumerable实现

[编辑我已更新以添加我的类定义,以清晰明了。IDataRepository包含返回IEnumerable的单个方法"retrieve",而IEntityRepository包含接受iInterface的单个void方法"save"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Repository<T>: IDataRepository<T>,IEntityRepository<T>
                        where T: class, IInterface
{
    protected virtual IEnumerable<T> Collection{ get; set;}
    public virtual void Bar(T thing)
    {
        try
        {
            if (Collection == null) return;
            Collection = (IEnumerable<T>)Collection.Foo(thing);

        }
        catch(Exception ex)
        {
            //breakpoint for debugging
        }
    }
}

foo的签名为IEnumerable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
internal static class MyExtensions
{
    internal static IEnumerable<IInterface> Foo(this ICollection<IInterface> c1,
                                                    IEnumerable<IInterface> c2)
    {
        //implementation removed for posting
        return c1;
    }
internal static IEnumerable<IInterface> Foo(this IEnumerable<IInterface> c1,
                                                    IInterface thing)
    {
        return Foo(c1, new List<IInterface>() { thing });
    }
}

作为IEnumerable,codelens报告每个foo有一个引用。客户机调用第二个函数,该函数包围第一个函数。每当我将这些转换为ICollection时,我在CodeLens中的引用就消失了,并且我得到了我在上面发布的异常……这对于我在引发异常时如何拥有ICollection的扩展方法毫无意义。下面是使用ICollections的foo接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
protected virtual ICollection<T> Collection { get; set;}
    public virtual void Bar(T thing)
    {
        try
        {
            if (Collection == null) return;
            Collection = (ICollection<T>)Collection.Foo(entity);

        }
        catch(Exception ex)
        {
            //breakpoint
        }
    }

internal static class MyExtensions
{
    internal static ICollection<IInterface> Foo(this ICollection<IInterface> c1,
                                                    IEnumerable<IInterface> c2)
    {
        //implementation removed for posting
        return c1;
    }
    internal static ICollection<IInterface> Foo(this ICollection<IInterface> c1,
                                                    IInterface thing)
    {
        return Foo(cache, new List<IInterface>() { thing });
    }
}

当从IEnumerable切换到ICollection时,是否有人能够识别出问题所在?


这是协方差问题。IEnumerable是协变的,ICollection不是协变的。

1
public interface IEnumerable<out T> : IEnumerable
1
public interface ICollection<T> : IEnumerable<T>, IEnumerable

您只能在IEnumerable声明中看到out关键字。

这就是为什么扩展方法只适用于ICollection,而不适用于ICollection

使您的扩展方法成为通用方法以使其工作:

1
2
3
4
5
6
7
8
9
10
11
12
internal static class MyExtensions
{
    internal static ICollection<T> Foo<T>(this ICollection<T> c1, IEnumerable<T> c2) where T : IInterface
    {
        //implementation removed for posting
        return c1;
    }
    internal static ICollection<T> Foo<T>(this ICollection<T> c1, T thing) where T : IInterface
    {
        return Foo(cache, new List<T>() { thing });
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
internal static class MyExtensions
{
    internal static ICollection<IInterface> Foo<T>(this ICollection<IInterface> c1, IEnumerable<T> c2) where T : IInterface
    {
        //implementation removed for posting
        return c1;
    }
    internal static ICollection<IInterface> Foo<T>(this ICollection<T> c1, T thing) where T : IInterface
    {
        return Foo(cache, new List<IInterface>() { thing });
    }
}

根据您想要它返回的内容:ICollectionICollection