C# 有没有办法从父类获取子类并检查(和使用)方法和属性?
我正在编写一个类,它将使用类并创建少量的信息报告。问题是,即使它们都从基类继承,这些子类也不必实现所有sames方法和属性。只是相关的 我不能强制转换这些类,因为在设计时我不知道将使用哪些类。。。我们有一个框架,在一个作业一个作业的基础上,开发人员接受它并实现一些特定于作业的代码。基类有一些必须实现的方法(Init、Report、Audit),但根据它是什么类型的作业,它将有几个属性中的一个或两个以及一两个方法。 所以(正如我下面简单的例子)他们可能实现Cat,但也需要第二个类,它与Cat相似,但不同程度足以保证一个新类,所以创建Cat2。 我知道这听起来很奇怪,但是当开发人员在使用框架时,他们正在使用他们的实例化类C# 有没有办法从父类获取子类并检查(和使用)方法和属性?,c#,C#,我正在编写一个类,它将使用类并创建少量的信息报告。问题是,即使它们都从基类继承,这些子类也不必实现所有sames方法和属性。只是相关的 我不能强制转换这些类,因为在设计时我不知道将使用哪些类。。。我们有一个框架,在一个作业一个作业的基础上,开发人员接受它并实现一些特定于作业的代码。基类有一些必须实现的方法(Init、Report、Audit),但根据它是什么类型的作业,它将有几个属性中的一个或两个以及一两个方法。 所以(正如我下面简单的例子)他们可能实现Cat,但也需要第二个类,它与Cat相似,
class Animal
{
////common stuff
public
}
class Cat : Animal
{
public Name { get; set; }
public Speak()
{
Console.WriteLine("Meow");
}
}
class Dog: Animal
{
public Name { get; set; }
public Speak()
{
Console.WriteLine("Woof");
}
}
class Person: Animal
{
public Title{ get; set; }
public Name { get; set; }
public Speak()
{
Console.WriteLine("Hello");
}
}
class Spider: Animal
{
public Name { get; set; }
}
List<Animal> animals = new List<Animals> {
new Cat { Name = "Bob" },
new Dog { Name = "Fido" },
new Person { Name = "Harry", Title = "Mr" },
new Spider { Name = "Boris" }
}
foreach (Animal item in animals)
{
///now is wishful pseudo code...
if item has Speak then speak()
if item has Title then write Title
if item has Name then write Name
}
class Animal
{
abstract Work();
}
class Cat : Animal
{
public Name;
public Speak();
override Work()
{
Speak();
Write Name;
}
}
class Person: Animal
{
public Title;
public Name;
public Speak();
override Work()
{
Speak();
Write Title;
Write Name;
}
}
foreach (Animal item in animals)
{
item.Work();
}
类动物
{
////普通的东西
公开的
}
类别猫:动物
{
公共名称{get;set;}
公开演讲
{
控制台。书写线(“喵喵”);
}
}
狗类:动物
{
公共名称{get;set;}
公开演讲
{
控制台。书写线(“Woof”);
}
}
上课人:动物
{
公共标题{get;set;}
公共名称{get;set;}
公开演讲
{
Console.WriteLine(“你好”);
}
}
类别:动物
{
公共名称{get;set;}
}
列出动物=新列表{
新类别{Name=“Bob”},
新狗{Name=“Fido”},
新人{Name=“Harry”,Title=“Mr”},
新蜘蛛{Name=“Boris”}
}
foreach(动物中的动物项目)
{
///现在是一厢情愿的伪代码。。。
如果项目有Speak,则Speak()
如果项目有标题,则写标题
如果项目有名称,则写下名称
}
我只想循环浏览这个列表,如果它有某个属性,那么就阅读它。如果它有一个特定的方法,那么调用它
如果它有一个特定的属性,那么阅读它。如果它有一个特定的方法,那么调用它
听起来这些功能都定义了一个接口
,即
interface IHazName{string Name{get;}
接口IHazTitle{string Title{get;}}
接口名称{void Speak();}
...
foreach(动物中的动物项目)
{
如果(项目为C)cs.Speak();
如果(项目名称为IHazTitle ht)写下(ht.Title);
如果(项目名称为IHazName hn)写下(hn.名称);
}
...
类别猫:动物,IHazName,ICanSpeak
{...}
狗类:动物,IHazName,我会说
{...}
上课人:动物,IHazName,IHazTitle,我会说
{...}
类蜘蛛:动物,名字
{...}
使用接口的一个特别好的地方是,您可以稍微捏造一下名称:
class狗:动物,IHazName,我会说
{
//...
public void Bark(){Say(“woof”);}//方法在公共API上称为Bark
void ICanSpeak.Speak()=>Bark();//但在ICanSpeak API上发言
}
注意:此处的用法如下:
如果(项目是ICanSpeak cs)cs.Speak();
需要现代C#编译器;如果您使用的是较旧的编译器,则:
if(item是icanstake)((icanstake)item.Speak();
或:
var cs=项目名称;
如果(cs!=null)cs.Speak();
同样地
Speak.Speak()=>Bark();
与旧编译器上的相同
Speak.Speak(){Bark();}
您可以添加一个新的抽象方法,然后在子类中实现它
class Animal
{
////common stuff
public
}
class Cat : Animal
{
public Name { get; set; }
public Speak()
{
Console.WriteLine("Meow");
}
}
class Dog: Animal
{
public Name { get; set; }
public Speak()
{
Console.WriteLine("Woof");
}
}
class Person: Animal
{
public Title{ get; set; }
public Name { get; set; }
public Speak()
{
Console.WriteLine("Hello");
}
}
class Spider: Animal
{
public Name { get; set; }
}
List<Animal> animals = new List<Animals> {
new Cat { Name = "Bob" },
new Dog { Name = "Fido" },
new Person { Name = "Harry", Title = "Mr" },
new Spider { Name = "Boris" }
}
foreach (Animal item in animals)
{
///now is wishful pseudo code...
if item has Speak then speak()
if item has Title then write Title
if item has Name then write Name
}
class Animal
{
abstract Work();
}
class Cat : Animal
{
public Name;
public Speak();
override Work()
{
Speak();
Write Name;
}
}
class Person: Animal
{
public Title;
public Name;
public Speak();
override Work()
{
Speak();
Write Title;
Write Name;
}
}
foreach (Animal item in animals)
{
item.Work();
}
您可以创建一个静态列表,并将所有实例放入该列表中,以便进行检查。您可以使用类似
if(animal is Cat){/*use Cat with all Cat properties and methods*/}
,但通常不建议这样做。如果你经常使用它,它会指出建筑/设计中的问题这是一个新的ish特性(C#7?);以前,你可以这样做:Cat=animalas-Cat;如果(cat!=null){[…]}
——另请参见:如果您“只是”想知道某个对象是否具有特定的属性和/或方法,反射可能会有所帮助,但这需要相当高的成本和性能。很抱歉延迟将其标记为正确答案。这真是一种享受,谢谢你。