Не удается реализовать элемент интерфейса, так как он не имеет соответствующего возвращаемого типа списка
У меня есть интерфейсы IChild и IParent. IParent имеет член, который является List<IChild>.
Я хочу иметь классы, реализующие IParent , где каждый класс имеет член, реализующий IChild:
public interface IChild
{
}
public interface IParent
{
List<IChild> a { get; set; }
}
public class ChildA : IChild
{
}
public class ChildB : IChild
{
}
public class ParentA : IParent
{
public List<ChildA> a { get; set; }
}
public class ParentB : IParent
{
public List<ChildB> a { get; set; }
}
Но этот код не будет компилироваться. Ошибка заключается в следующем:
`MyApp.Data.ParentA` does not implement interface member `MyApp.Data.IParent.a`.
`MyApp.Data.ParentA.a` cannot implement `MyApp.Data.IParent.a` because it does not have
the matching return type of `System.Collections.Generic.List<MyApp.Data.IChild>`.
5 ответов:
Сделать IParent generic:
public interface IChild { } public interface IParent<TChild> where TChild : IChild { List<TChild> a { get; set; } } public class ChildA : IChild { } public class ChildB : IChild { } public class ParentA : IParent<ChildA> { public List<ChildA> a { get; set; } } public class ParentB : IParent<ChildB> { public List<ChildB> a { get; set; } }
Вам нужно, чтобы классы возвращали a
List<IChild>:public class ParentA : IParent { public List<IChild> a { get; set; } } public class ParentB : IParent { public List<IChild> a { get; set; } }
Реализация может возвращать только список IChild следующим образом:
public interface IChild { } public interface IParent { List<IChild> Children { get; set; } } public class ChildA : IChild { } public class ChildB : IChild { } public class ParentA : IParent { public List<IChild> Children { get; set; } } public class ParentB : IParent { public List<IChild> Children { get; set; } }
Коллекция
IChildне может быть неявно преобразована в коллекцию ее дочернего типаИзмените тип возвращаемого значения
IParent.aнаList<ChildA>или измените объявление свойства наParentAиParentBнаpublic List<IChild> a { get; set; }. Я рекомендую последнее, так как я думаю, что это то, что вы, скорее всего, собираетесь сделать.
У меня было аналогичное требование, когда я имел два разных метода, которые работали с двумя разными классами, но имели одинаковую логику в нем для свойств, общих для обоих классов.
Таким образом, я думал использовать наследование и генерики для этого, чтобы написать общий метод, я смог достичь следующим образом.namespace OOPS.Interfaces { using System.Collections.Generic; public interface IBanner { string Name { get; set; } } public interface IBannerContent<T> where T : IBanner { List<T> Banners { get; set; } } }Простая Модель.
namespace OOPS.Simple { using Interfaces; using System.Collections.Generic; public class Banner : IBanner { public string Name { get; set; } } public class BannerContent : IBannerContent<Banner> { public List<Banner> Banners { get; set; } } }Сложная Модель.
namespace OOPS.Complex { using Interfaces; using System.Collections.Generic; public class Banner : IBanner { public string Name { get; set; } public string Description { get; set; } } public class BannerContent : IBannerContent<Banner> { public List<Banner> Banners { get; set; } } }Общая бизнес-логика и образец вызова. Ключевой частью здесь является использование
whereпредложение для ограничения типа, такого какwhere T : IBanner, вплоть до метода, который мы хотим, чтобы он был общим.namespace OOPS { using Interfaces; using System; using System.Collections.Generic; public class BusinessLogic { public void Print<T>(IBannerContent<T> bannerContent) where T : IBanner { foreach (var item in bannerContent.Banners) { Console.WriteLine(item.Name); } } } class Program { static void Main(string[] args) { var banner1 = new Simple.BannerContent { Banners = new List<Simple.Banner> { new Simple.Banner { Name = "Banner 1" }, new Simple.Banner { Name = "Banner 2" } } }; var banner2 = new Complex.BannerContent { Banners = new List<Complex.Banner> { new Complex.Banner { Name = "Banner 3", Description = "Test Banner" }, new Complex.Banner { Name = "Banner 4", Description = "Design Banner" } } }; var business = new BusinessLogic(); business.Print(banner1); business.Print(banner2); Console.ReadLine(); } } }
Comments