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时,是否有人能够识别出问题所在?
这是协方差问题。
1 | public interface IEnumerable<out T> : IEnumerable |
1 | public interface ICollection<T> : IEnumerable<T>, IEnumerable |
您只能在
这就是为什么扩展方法只适用于
使您的扩展方法成为通用方法以使其工作:
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 }); } } |
根据您想要它返回的内容: