我的代码出了问题。我是继承人的新手(到目前为止只有1次讲座)并且非常感谢这里的任何帮助。我已经得到了这个问题,并认为我已经完成了它。创建一个Book类,添加两个子类。全部显示。加上其他东西,但这是核心问题。
当我尝试在for循环中显示每个对象及其信息时,我无法弄清楚如何访问TextBook的BookGrade。我制作了一系列书籍,并将所有内容都放在那里。我知道这不对,但我不知道从哪里开始。我试过制作像这样的TextBooks数组
TextBook[] bookArray = new TextBook[3] { Book1, TBook1, CBook1};
但是后来我需要为Book1添加一个强制转换器,但是我仍然无法将类型'CoffeeTableBook'隐式转换为'TextBook'。我得到了这个,但不知道如何绕过它。我收到此错误“'Book'不包含'BookGrade'的定义。”
我有3个班,Book,TextBook和CoffeeTableBook。 TextBook和CoffeeTableBook类都派生自Book类。
提前感谢任何花时间帮助我的人。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BookDemo
{
class Program
{
static void Main(string[] args)
{
//Book
Book Book1 = new Book();
Book1.BookNum = 123456;
Book1.BookTitle = "Harry Potter 1";
Book1.BookAuthor = "JK Rowling";
Book1.BookPrice = 5.95;
//Text Book
TextBook TBook1 = new TextBook();
TBook1.BookNum = 123436;
TBook1.BookTitle = "Harry Potter 2";
TBook1.BookAuthor = "JK Rowling";
TBook1.BookPrice = 5.95;
TBook1.BookGrade = "A";
//Coffee Table Book
CoffeeTableBook CBook1 = new CoffeeTableBook();
CBook1.BookNum = 123136;
CBook1.BookTitle = "Harry Potter 7";
CBook1.BookAuthor = "JK Rowling";
CBook1.BookPrice = 95.95;
Book[] bookArray = new Book[3] { Book1, TBook1, CBook1 };
for (int i = 0; i < bookArray.Length; i++)
{
if (bookArray[i].GetType() == typeof(TextBook))
{
Console.WriteLine("{0} {1} {2} {3} {4}", bookArray[i].BookNum, bookArray[i].BookTitle, bookArray[i].BookAuthor, bookArray[i].BookPrice, bookArray[i].BookGrade);//'Book' does not contain a defination for 'BookGrade'..
}
else
{
Console.WriteLine("{0} {1} {2} {3} {4}", bookArray[i].BookNum, bookArray[i].BookTitle, bookArray[i].BookAuthor, bookArray[i].BookPrice, "N/A");
}
}
}
}
}
class Book
{
public int BookNum { get; set; }
public string BookTitle { get; set; }
public string BookAuthor { get; set; }
public double BookPrice { get; set; }
}
class TextBook : Book // must be priced between $20.00 and $80.00
{
const double MIN_PRICE = 20;
const double MAX_PRICE = 80;
public string BookGrade { get; set; }
new public double BookPrice
{
set
{
if (value < MIN_PRICE)
{
base.BookPrice = MIN_PRICE;
}
else if (value > MAX_PRICE)
{
base.BookPrice = MAX_PRICE;
}
else
{
base.BookPrice = value;
}
}
get
{
return base.BookPrice;
}
}
}
class CoffeeTableBook : Book //must be priced between $35.00 and $100.00
{
const double MIN_PRICE = 35;
const double MAX_PRICE = 100;
new public double BookPrice
{
set
{
if (value < MIN_PRICE)
{
base.BookPrice = MIN_PRICE;
}
else if (value > MAX_PRICE)
{
base.BookPrice = MAX_PRICE;
}
else
{
base.BookPrice = value;
}
}
get
{
return base.BookPrice;
}
}
}
答案 0 :(得分:1)
您需要在if(bookArray [i] .GetType()== typeof(TextBook)) - 分支
中强制转换为特定类型的教科书例如:
if (bookArray[i].GetType() == typeof(TextBook))
{
Console.WriteLine("{0} {1} {2} {3} {4}", bookArray[i].BookNum, bookArray[i].BookTitle, bookArray[i].BookAuthor, bookArray[i].BookPrice, ((TextBook)bookArray[i]).BookGrade); // Works now, because we view bookArray[i] as TextBook and not it's underlaying type
}
else
{
Console.WriteLine("{0} {1} {2} {3} {4}", bookArray[i].BookNum, bookArray[i].BookTitle, bookArray[i].BookAuthor, bookArray[i].BookPrice, "N/A");
}
我通常建议使用here所述的新Switch-Capabilities(模式),但我不想干扰你的老师。
答案 1 :(得分:1)
另外,您可以重新定义类并避免在for:
中检查类型class Book
{
public int BookNum { get; set; }
public string BookTitle { get; set; }
public string BookAuthor { get; set; }
public double BookPrice { get; set; }
public string BookGrade = "N/A";
}
class TextBook : Book // must be priced between $20.00 and $80.00
{
const double MIN_PRICE = 20;
const double MAX_PRICE = 80;
public string BookGrade { get; set; }
new public double BookPrice
{
set
{
if (value < MIN_PRICE)
{
base.BookPrice = MIN_PRICE;
}
else if (value > MAX_PRICE)
{
base.BookPrice = MAX_PRICE;
}
else
{
base.BookPrice = value;
}
}
get
{
return base.BookPrice;
}
}
}
class CoffeeTableBook : Book //must be priced between $35.00 and $100.00
{
const double MIN_PRICE = 35;
const double MAX_PRICE = 100;
new public double BookPrice
{
set
{
if (value < MIN_PRICE)
{
base.BookPrice = MIN_PRICE;
}
else if (value > MAX_PRICE)
{
base.BookPrice = MAX_PRICE;
}
else
{
base.BookPrice = value;
}
}
get
{
return base.BookPrice;
}
}
}
并在主要内容:
foreach (Book singleBook in BookArray)
{
Console.WriteLine("{0} {1} {2} {3} {4}", singleBook.BookNum, singleBook.BookTitle, singleBook.BookAuthor, singleBook.BookPrice, singleBook.BookGrade);
}
答案 2 :(得分:1)
您可以覆盖'toString()'方法来设置显示对象的确切方式
class Program
{
class Book
{
public int BookNum { get; set; }
public string BookTitle { get; set; }
public string BookAuthor { get; set; }
public double BookPrice { get; set; }
public override string ToString() //!
{
return string.Format("{0} {1} {2} {3}", this.BookNum, this.BookTitle, this.BookAuthor, this.BookPrice);
}
}
class TextBook : Book // must be priced between $20.00 and $80.00
{
const double MIN_PRICE = 20;
const double MAX_PRICE = 80;
public string BookGrade { get; set; }
new public double BookPrice
{
set
{
if (value < MIN_PRICE)
{
base.BookPrice = MIN_PRICE;
}
else if (value > MAX_PRICE)
{
base.BookPrice = MAX_PRICE;
}
else
{
base.BookPrice = value;
}
}
get { return base.BookPrice; }
}
public override string ToString() //!
{
return base.ToString() + " " + this.BookGrade;
}
}
class CoffeeTableBook : Book //must be priced between $35.00 and $100.00
{
const double MIN_PRICE = 35;
const double MAX_PRICE = 100;
new public double BookPrice
{
set
{
if (value < MIN_PRICE)
{
base.BookPrice = MIN_PRICE;
}
else if (value > MAX_PRICE)
{
base.BookPrice = MAX_PRICE;
}
else
{
base.BookPrice = value;
}
}
get { return base.BookPrice; }
}
}
private static void Main(string[] args)
{
//Book
var book1 = new Book
{
BookNum = 123456,
BookTitle = "Harry Potter 1",
BookAuthor = "JK Rowling",
BookPrice = 5.95
};
//Text Book
var TBook1 = new TextBook
{
BookNum = 123436,
BookTitle = "Harry Potter 2",
BookAuthor = "JK Rowling",
BookPrice = 5.95,
BookGrade = "A"
};
//Coffee Table Book
var CBook1 = new CoffeeTableBook
{
BookNum = 123136,
BookTitle = "Harry Potter 7",
BookAuthor = "JK Rowling",
BookPrice = 95.95
};
var bookArray = new Book[] {book1, TBook1, CBook1};
foreach (Book t in bookArray)
{
Console.WriteLine(t); //! i.e Console.WriteLine(t.ToString());
}
}
答案 3 :(得分:1)
您可以用更短的格式重写for循环:
string output;
foreach (Book bk in bookArray)
{
output = string.Format(
"{0} {1} {2} {3} {4}",
bk.BookNum,
bk.BookTitle,
bk.BookAuthor,
bk.BookPrice,
(bk is TextBook)
? (bk as TextBook).BookGrade
: "N/A");
Console.WriteLine(output);
}
答案 4 :(得分:0)
想象一下,如果你添加更多来自Book
的类会发生什么,你的代码最终会变得笨拙
if(book.GetType() == typeof(TextBook))
{
}
if(book.GetType() == typeof(CoffeeTableBook))
{
}
if(book.GetType() == typeof(AnotherBookType))
{
}
if(book.GetType() == typeof(MagicalSpellsBook))
{
}
if(book.GetType() == typeof(Whatever))
{
}
如果实际显示Book
的代码发挥作用,情况会变得更糟。
你能做些什么来解决这个问题?首先介绍BookRenderer
class BookRenderer
{
List<ISpecificBookRenderer> specificBookRenderers = ...; // pass via constructor
public void RenderBook(Book b)
{
var matchingRenderer = specificBookRenderers.First(r => r.BookType == b.GetType());
matchingRenderer.RenderBook(b);
}
}
从ISpecificBookRenderer
派生的类型负责呈现您的图书。接口ISpecificBookRenderer
定义为
interface ISpecificBookRenderer
{
Type BookType { get; }
void RenderBook(Book b);
}
现在,您可以为从Book
派生的每种类型创建渲染器,例如
class TextBookRenderer
{
public Type BookType => typeof(TextBook);
public void RenderBook(Book b)
{
if(b is TextBoox textBook)
{
// output TextBook value
}
throw new ArgumentException("Passed book is not a TextBook", nameof(b));
}
}
当然这需要付出代价,但是单班保持干净整洁。此外,可以想象需要将您的书籍呈现给不同的系统。通过引入这些渲染器,您可以交换实现,而无需更改实际的类。 并且你不会混淆业务逻辑(你的Book
类 - 他们就是这种情况,因为他们执行价格检查)和演示,你会这样做,如果您只需覆盖ToString
即可获得所需的演示文稿。