3

我有两个接口,一个包含另一个接口的列表,我想要一个实现第一个接口的类,但有一个实现第二个接口的另一个类的列表,而不仅仅是一个接口列表。例子:

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

显然它不喜欢这样。有没有正确的方法来做我想做的事情,或者我只需要在我想使用它时制作BookShelfhave aList<IBook>并将每个IBook转换为 a ?Book在这里寻找可以帮助我的模式。谢谢。

4

4 回答 4

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; }
} 
于 2012-08-22T20:51:17.263 回答
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,您给出的接口 - 但它最终将 a 添加EvilBook到 aList<Book>中,这肯定是不正确的。我经常发现,如果编译器阻止我做某事,那么想想如果它让我继续我的坏主意我可能会遇到什么问题是有用的。

您可能要考虑使IBookShelf通用:

public interface IBookShelf<T> where T : IBook
{
    long Stuff { get; set; }
    List<T> Books { get; set; }
}

然后:

public class BookShelf : IBookShelf<Book>

...但这实际上取决于您要实现的目标。

您可能还想问自己,您是否真的需要该接口……IBook以及您是否真的想要.Books


1无论如何,编译器会识别:)

于 2012-08-22T20:51:21.180 回答
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; }
    }
}
于 2012-08-22T20:52:24.787 回答
0
  1. 一般来说,铸造是可疑的,最好避免。这是一个很好的信号,表明有些事情是不对的。

  2. 要修复您需要更改的代码

    public List<Book> Books { get; set; }
    

    public List<IBook> Books { get; set; }
    
  3. 你可以而且应该更概括一些事情。什么样的书架不能放其他物品?我还没有看到一个。考虑一下:

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'
    }
}

于 2016-02-15T13:47:57.007 回答