提问人:TheMostEpic 提问时间:12/13/2019 更新时间:12/13/2019 访问量:500
当 List<Interface> 对象属性的类继承自 interface 时,如何访问它?
How to access List<Interface> object properties when it's class is inherited from interface?
问:
好的,这就是问题所在。我有一个接口 IBook,其中包括属性 Name。有两个类继承自 IBook 并添加自己的属性 Genre。我想创建一个字典或一个列表,并在其中添加各种书籍,并通过字符串及其属性访问它们,所以我将其设置为字典。在示例中,我可以访问 books[“LOTR”]。名称但不是书籍[“LOTR”]。Genre,因为 Name 是 IBook 接口的属性,而 Genre 是从 IBook 继承的类的属性。
是否可以使 Dictionary 或 List 与接口类型一起使用,并且仍然能够访问所有继承的类属性,或者我应该使用数组或其他东西?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp124
{
interface IBook
{
string Name { get; set; }
}
public class FantasyBook:IBook
{
string name;
string genre;
public string Name
{
get { return name; }
set { name = value; }
}
public string Genre
{
get { return genre; }
set { genre = value; }
}
}
public class HorrorBook : IBook
{
string name;
string genre;
public string Name
{
get { return name; }
set { name = value; }
}
public string Genre
{
get { return genre; }
set { genre = value; }
}
}
class Program
{
static void Main(string[] args)
{
FantasyBook LordOfTheRings = new FantasyBook();
HorrorBook Frankenstein = new HorrorBook();
Dictionary<string, IBook> books = new Dictionary<string,
IBook>();
books.Add("LOTR", LordOfTheRings);
books.Add("Frankenstein", Frankenstein);
books["LOTR"].Name = "Lord Of The Rings";
books["LOTR"].Genre = "Fantasy";
Console.ReadLine();
}
}
}
答:
1赞
timur
12/13/2019
#1
注释非常到位 - 你不能这样做,因为编译器会检查 上的可用成员(因为你声明了它),并且不会让你通过尝试访问未在那里定义的属性来搬起石头砸自己的脚。这是静态类型检查。IBook
但是,让我们想象一下,您不关心类型安全性和性能。事实证明,你有一个选择。嗯,有点......因为您仍然必须放弃您的特定IBook
dynamic
interface IBook {
string Name { get; set; }
}
public class FantasyBook : IBook
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class HorrorBook : IBook
{
public string Name {get;set;}
public string Genre {get;set;}
}
public class BadaBook : IBook // so I added this new class that does not implement Genre to illustrate a point
{
public string Name { get; set; }
}
static void Main(string[] args)
{
var LordOfTheRings = new FantasyBook();
var Frankenstein = new HorrorBook();
var Badaboom = new BadaBook();
Dictionary<string, dynamic> books = new Dictionary<string, dynamic>();
books.Add("LOTR", LordOfTheRings);
books.Add("Frankenstein", Frankenstein);
books.Add("Badaboom", Badaboom);
books["LOTR"].Name = "Lord Of The Rings";
books["LOTR"].Genre = "Fantasy";
books["Badaboom"].Name = "We can easily assign Name as it is defined. No problem here";
books["Badaboom"].Genre = "But we will miserably fail here"; // RuntimeBinderException: 'UserQuery.BadaBook' does not contain a definition for 'Genre'
Console.ReadLine();
}
查看动态以进一步阅读。它伴随着我示例中概述的风险以及性能损失。它本身并不坏,只是需要适度服用。
评论
0赞
TheMostEpic
12/13/2019
帖木儿的回答应该有效。非常感谢!我知道我需要非常小心动态,而不是创建运行时错误问题。
3赞
John Alexiou
12/13/2019
#2
另一种方法是添加另一层接口,并使用模式匹配来访问属性:Genre
interface IBook
{
string Name { get; set; }
}
interface IBookWithGenre : IBook
{
string Genre { get; set; }
}
public class FantasyBook : IBookWithGenre
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class HorrorBook : IBookWithGenre
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class SimpleBook : IBook
{
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
FantasyBook LordOfTheRings = new FantasyBook();
HorrorBook Frankenstein = new HorrorBook();
SimpleBook abook = new SimpleBook();
var books = new Dictionary<string, IBook>
{
{ "LOTR", LordOfTheRings },
{ "Frankenstein", Frankenstein },
{ "Simple", abook },
};
books["LOTR"].Name = "Lord Of The Rings";
if (books["LOTR"] is IBookWithGenre withGenre)
{
withGenre.Genre = "Fantasy";
}
Console.ReadLine();
}
}
评论
(books["LOTR"] as FantasyBook).Genre
Genre
IBook
BaseBook
Name
Name