扩展基类方法

时间:2011-03-23 03:21:17

标签: c# .net inheritance extension-methods

我是C#的新手,我正在尝试理解基本概念。预先感谢您的帮助。我在下面有一些示例类(在此窗口中键入,因此可能存在一些错误)并且有两个问题:

  1. 是否可以调用以相同名称执行基类方法中的代码的派生类方法,然后在派生类方法中执行代码?每个派生类都需要为RunCheck执行基类代码,然后执行特定于其类的专用代码。我可以在基类中命名RunCheck(),然后在调用派生类的RunCheck()时调用它,但是我必须记得在派生类的RunCheck()上调用它。

  2. 在Program.cs中,我想输出一个空白值的字段,如果它位于我传入的派生类中的字段上。我会传入什么内容?

  3. 这是我的代码:

      class baseCheck
      {
          public DateTime StartTime { get; set; }
          public DateTime LastRun { get; set; }
          public int Runs { get; set; }
          //Others
    
          public void RunCheck()
          {
             if (Started != null)
               started = DateTime.Now;
    
             LastRun = DateTime.Now;
    
             Runs++;
          }
        }
    
        class FileCheck : baseCheck
        {
           public string FileName { get; set; }
    
           public void RunCheck()
           {
               //I want all the code in the base class to run plus
               //any code I put here when calling this class method
    
            }
        }
        class DirectoryCheck : baseCheck
        {
           public string DirectoryName { get; set; }
    
           public void RunCheck()
           {
               //I want all the code in the base class to run plus
               //any code I put here when calling this class method
    
            }
        }
    
            //Program.cs
            static void Main()
            {
               //Create derived class - either DirectoryCheck or FileCheck
               //depending on what the user chooses.
    
                if (Console.ReadLine()=="F")
                {
                    FileCheck c = new FileCheck();  
                }
                else
                {
                    DirectoryCheck c = new DirectoryCheck();
                }
    
                PrintOutput(c);
    
            }
            private void PrintOut(What do I put here?)
            {
               Console.WriteLine("Started: {0}",f.StartTime)
               Console.WriteLine("Directory: {0}", f.DirectoryName)
               Console.WriteLine("File: {0}", f.FileName}
            }
    

2 个答案:

答案 0 :(得分:26)

只需在base.RunCheck()课程中致电DirectoryCheck

public class DirectoryCheck : baseCheck
{
    public string DirectoryName { get; set; }

    public void RunCheck()
    {
        //I want all the code in the base class to run plus
        //any code I put here when calling this class method
        base.RunCheck();
        Console.WriteLine("From DirectoryCheck");
    }
}

对于当前的实现,您隐藏了基类RunCheck()方法 - 您应该覆盖它 - 这会将基类中的方法签名更改为

    public virtual void RunCheck()

并在派生类中

    public override void RunCheck()

我怀疑你真正想要的是Non Virtual interface模式(NVI) - 在你的基类中暴露一个受保护的虚方法,子类可以覆盖,但在基类上有一个公共方法实际上是在内部调用该方法 - 这种方法允许您扩展在调用之前和之后所做的事情。

在您的示例中,这将如下所示:

class BaseCheck
{
    private DateTime Started { get; set; }
    public DateTime StartTime { get; set; }
    public DateTime LastRun { get; set; }
    public int Runs { get; set; }
    //Others

    public void RunCheck()
    {
        if (Started != null)
            Started = DateTime.Now;

        LastRun = DateTime.Now;
        Runs++;
        CoreRun();
    }

    protected virtual void CoreRun()
    {

    }
}


public class DirectoryCheck : BaseCheck
{
    public string DirectoryName { get; set; }

    protected override void CoreRun()
    {
        //I want all the code in the base class to run plus
        //any code I put here when calling this class method
        Console.WriteLine("From DirectoryCheck");
    }
}

答案 1 :(得分:3)

在派生类中,您可以使用:

在基类中调用该方法
public override void RunCheck()
{
    base.RunCheck();

    // Followed by the implementation of the derived class
}

如评论中所述,基本方法需要声明为virtual以允许覆盖:

public virtual void RunCheck() { ... }

对于您的PrintOut()方法,没有神奇的方法,但您可以将基类作为参数,然后测试类型。

private void PrintOut(baseCheck f)
{
   Console.WriteLine("Started: {0}", f.StartTime)
   Console.WriteLine("Directory: {0}", f.DirectoryName)

   if (check is FileCheck)
   {
       Console.WriteLine("File: {0}", ((FileCheck)f).FileName}
   }
}

或者您可以使用重载:

private void PrintOut(baseCheck f)
{
   Console.WriteLine("Started: {0}", f.StartTime)
   Console.WriteLine("Directory: {0}", f.DirectoryName)
}

private void PrintOut(FileCheck f)
{
    PrintOut((baseCheck)f);

    Console.WriteLine("File: {0}", ((FileCheck)f).FileName}
}

或者您可以将PrintOut方法作为课程的一部分(甚至可以使用现有的ToString()方法)并根据需要覆盖它。