【问题标题】:Calling derived class methods in a foreach loop在 foreach 循环中调用派生类方法
【发布时间】:2013-09-24 02:03:06
【问题描述】:

这段代码有问题:

List<Person> persons;    

foreach(var p in persons)
    p.Save();

有几个派生自Person 的类,它们都有自己的new Save() 方法。不幸的是,上面的代码只调用了基类的保存方法,尽管列表包含不同类型的实例(基类和派生类)。

所有派生类都包含所有基类的字段,只有Save方法不同,所以它也保存了派生类的字段。

如何根据当前迭代的变量类型使该循环调用适当的Save 方法?

【问题讨论】:

  • 你能举一个派生类的保存方法的例子吗?
  • @JustinPihony 这有什么帮助?
  • 你能告诉我们保存方法是如何定义的吗?它在 Person 类上被定义为 virtual 对吗?
  • 如果您使用new Save(),您将无法通过典型的方法覆盖/继承方式调用该方法。请查看新关键字的作用,在这种情况下,这与您希望它做的基本相反。
  • 好吧。这可能是问题所在。如何修改基础方法和派生方法以使其正常工作?

标签: c# oop foreach var


【解决方案1】:

方法隐藏通常是灾难的根源。此场景的正确实现将在Person 类中将Save() 声明为virtual,在派生类中将override 声明为。

要使其在您的情况下如上所述工作,您需要将p 转换为适当的派生类并在其上调用Save()。根据您对对象的了解或不了解,您可能需要动态确定派生类型并使用反射调用其Save() 方法。

【讨论】:

    【解决方案2】:

    另一种方式,使用反射

    List<Person> persons;    
    
    foreach(var p in persons)
        p.GetType().GetMethod("Save").Invoke(p, null);
    

    反射有点慢如果您可以将保存方法的声明更改为虚拟并在其他类中覆盖它,这将是比 lc 的答案更好的选择。

    【讨论】:

    • 我刚刚打了这个,它工作。有点奇怪,没有一种直接的方法可以做到这一点而不诉诸反射。
    • 这里 直接执行此操作而不诉诸反射,但是您已经定义了没有虚拟方法的基类,这与您通常会做的相反您希望能够在这些子类中调用被覆盖的方法。
    【解决方案3】:

    这调用了正确的方法。

    using System;
    
    namespace Inheritance
    {
        class Program
        {
            public class Person
            {
                virtual public void Save()
                {
                    Console.WriteLine("Person Save");
                }
            }
            public class Emp : Person
            {
                override public void Save() {
                    Console.WriteLine("Emp Save");
                }
            }
            static void Main(string[] args)
            {
                Person p = new Emp();
                p.Save();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-25
      • 2014-09-05
      • 2019-11-16
      • 2012-05-31
      • 2013-03-23
      • 1970-01-01
      • 2014-03-17
      • 2016-01-01
      相关资源
      最近更新 更多