我将IEnumerable <t>实现切换到ICollection <t> </t> </t>时遇到困难

时间:2014-02-15 14:20:18

标签: c# extension-methods ienumerable icollection

这让我疯狂,所以我想我会把它扔到社区而不是把头撞到我的桌子上。

我正在将我的应用程序区域从使用IEnumerable切换到ICollection。 我在IEnumerableOfIInterfaceExtensions中定义了几个扩展方法,我想将它们转换为ICollectionOfIInterfaceExtensions,并且在我将所有内容切换到封面后但是当我在我的存储库中切换出集合时,我得到(意外)错误:

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”

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

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有1个引用。客户端调用第二个包围第一个的客户端。每当我将它们切换到ICollection时,我在CodeLens中的引用就会消失,并且我得到了上面发布的异常......这就像在选择扩展方法时在ICollection上抛出异常一样毫无意义。这是Foo使用ICollections的界面

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时问题是什么?

1 个答案:

答案 0 :(得分:4)

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

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

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

这就是为什么您的扩展方法仅适用于ICollection<IInterface>,而不适用于ICollection<ClassWhichImplementsIInterface>

使您的扩展方法通用以使其正常工作:

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 });
    }
}

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 });
    }
}

根据您的要求返回:ICollection<IInterface>ICollection<T>