我有两个接口,一个包含另一个接口的列表,我希望有一个实现第一个接口的类,但是有一个实现第二个接口而不仅仅是接口列表的另一个类的列表。例如:
namespace TestInheritance
{
public interface IBookShelf
{
long Stuff { get; set; }
List<IBook> Books { get; set; }
}
public interface IBook
{
string Name { get; set; }
}
public class BookShelf : IBookShelf
{
public long Stuff { get; set; }
public List<Book> Books { get; set; }
}
public class Book : IBook
{
public string Name { get; set; }
}
}
显然它不喜欢这个。是否有正确的方法来做我想做的事情,或者我只需要让BookShelf
拥有List<IBook>
并将每个IBook
投放到Book
时我想用它吗?寻找可以帮助我在这里的模式。感谢。
答案 0 :(得分:4)
在将通用参数约束为IBookShelf
IBook
通用
然后你可以:
public interface IBookShelf<T> where T : IBook
{
long Stuff { get; set; }
List<T> Books { get; set; }
}
public class BookShelf : IBookShelf<Book>
{
public long Stuff { get; set; }
public List<Book> Books { get; set; }
}
答案 1 :(得分:2)
目前尚不清楚 正在尝试做什么 - 而且怀疑它甚至不清楚。为什么您特别希望BookShelf.Books
成为List<Book>
?为什么限制本身仅包含Book
值而不是IBook
值?我建议你考虑在这种情况下你想要发生什么:
public class EvilBook : IBook
{
public string Name { get; set; }
}
IBookShelf bookShelf = new BookShelf() { Books = new List<Book>() };
bookShelf.Books.Add(new EvilBook());
该代码中没有任何内容可疑 1 ,包含您提供的接口 - 但最终会在EvilBook
中添加List<Book>
,这肯定不是对。我经常发现,如果编译器阻止我做某事,那么考虑一下我可能遇到的问题是有用的,如果它让我继续我的坏主意。
您可能希望考虑制作IBookShelf
通用:
public interface IBookShelf<T> where T : IBook
{
long Stuff { get; set; }
List<T> Books { get; set; }
}
然后:
public class BookShelf : IBookShelf<Book>
......但这实际上取决于你想要达到的目标。
您可能还想问自己,您是否真的首先需要IBook
界面...以及您是否真的需要{{1}的公共可写属性}。
1 无论如何,编译器会认识到:)
答案 2 :(得分:0)
这样的事情怎么样:
namespace TestInheritance
{
public interface IBookShelf <TBook> where TBook : IBook
{
long Stuff { get; set; }
List<TBook> Books { get; set; }
}
public interface IBook
{
string Name { get; set; }
}
public class BookShelf : IBookShelf<Book>
{
public long Stuff { get; set; }
public List<Book> Books { get; set; }
}
public class Book : IBook
{
public string Name { get; set; }
}
}
答案 3 :(得分:0)
一般来说,施法是可疑的,最好避免。这是一个很好的信号,表明某些事情是不对的。
修复需要更改的代码
public List<Book> Books { get; set; }
到
public List<IBook> Books { get; set; }
你可以而且应该更多地概括一些事情。什么样的书架不允许其他物品?我还没看到一个。考虑一下:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public interface IShelf
{
long Stuff { get; }
List<IShelfItem> Items { get; }
}
public interface IShelfItem
{
string Name { get; }
string Thought {get; set;}//What do I think about it?
}
public class Shelf : IShelf
{
public Shelf(long stuff, string color)
{
Stuff = stuff;
Items = new List<IShelfItem>();
Color = color;
}
public long Stuff { get; private set; }
public List<IShelfItem> Items { get; private set; }//Note, you can still add to the list.
public string Color { get; set; }
}
public class Book : IShelfItem
{
public Book( string name, string thought ) {
Name = name;
Thought = thought;
}
public string Name { get; private set; }//Books that are on shelves don't really change their name;
public string Thought { get; set; }
public string BookSpecificProperty { get; set; }
}
public static void Main()
{
Shelf myShelf = new Shelf(42, "Dull boring grey");
myShelf.Color = "Red";
IShelf myIShelf = myShelf;
//myIShelf.Color = "Red"; - 'IShelf' does not contain a definition for 'Color'
myShelf.Items.Add( new Book("Title 1", "Such a great book" ) );
//Eos pass
var book = myShelf.Items.SingleOrDefault( i => i.Name == "Title 1" );
if( book != null ) {
book.Thought = "I used to think it was such a great book. It's just OK";
//book.BookSpecificProperty = "X"; - 'IShelfItem' does not contain a definition for 'BookSpecificProperty'
}
}
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public interface IShelf
{
long Stuff { get; }
List<IShelfItem> Items { get; }
}
public interface IShelfItem
{
string Name { get; }
string Thought {get; set;}//What do I think about it?
}
public class Shelf : IShelf
{
public Shelf(long stuff, string color)
{
Stuff = stuff;
Items = new List<IShelfItem>();
Color = color;
}
public long Stuff { get; private set; }
public List<IShelfItem> Items { get; private set; }//Note, you can still add to the list.
public string Color { get; set; }
}
public class Book : IShelfItem
{
public Book( string name, string thought ) {
Name = name;
Thought = thought;
}
public string Name { get; private set; }//Books that are on shelves don't really change their name;
public string Thought { get; set; }
public string BookSpecificProperty { get; set; }
}
public static void Main()
{
Shelf myShelf = new Shelf(42, "Dull boring grey");
myShelf.Color = "Red";
IShelf myIShelf = myShelf;
//myIShelf.Color = "Red"; - 'IShelf' does not contain a definition for 'Color'
myShelf.Items.Add( new Book("Title 1", "Such a great book" ) );
//Eos pass
var book = myShelf.Items.SingleOrDefault( i => i.Name == "Title 1" );
if( book != null ) {
book.Thought = "I used to think it was such a great book. It's just OK";
//book.BookSpecificProperty = "X"; - 'IShelfItem' does not contain a definition for 'BookSpecificProperty'
}
}