如何将枚举值作为参数

时间:2016-06-16 02:09:21

标签: c# inheritance enums

我自己从一本书中学习C#并且不明白我在这里做错了什么。我有一个基类抽象类Employee,类Director继承自,类Partner继承自该类。我想根据带有职位的枚举类型在Partner类中设置职称。假设以下(MWE)代码:

public abstract class Employee
{
    protected string title = "Employee";  // underlying field

    public string Title { get { return title; } }  // read-only property

    public Employee() { // do some stuff all children need }  // constructor

    public virtual void Display()
    {
        Console.WriteLine("Title: {0}", Title);
    }
}


public class Director : Employee
{
    protected new string title = "Director";  // shadowing field works here

    public int NumberOfProjectsManaged { get; set; }  // additional property

    public Director() : base() { NumberOfProjectsManaged = 0; } // constructor

    public override void Display()
    {
        base.Display();
        Console.WriteLine("Number of Projects Managed: {0}", NumberOfProjectsManaged);
    }
}


public class Partner : Director
{
    // there are more than two in the actual code, but this is a MWE
    public enum SpecificTitle
    {
      Principal,
      Partner
    };

    public Partner() : base() 
    {
        this._setTitle(SpecificTitle.Partner);  // defaults to Partner
    }

    public Partner(SpecificTitle jobTitle) 
    {
        this._setTitle(jobTitle);  // overloaded ctor allows user to specify
    }

    private void _setTitle(SpecificTitle jobTitle)
    {
        switch (jobTitle)
        {
            case SpecificTitle.Principal:
                this.title = "Principal";
                break;
            case SpecificTitle.Partner:
            default:
                this.title = "Partner";
                break;
        }
    }
}

Director班级工作正常,标题总是"导演"如预期的。但是,Partner类的标题始终为"员工"而不是"合作伙伴"或"校长"。如果我只使用默认构造函数,那无关紧要:

Partner DefaultTitle = new Partner();  // title = "Employee"

或者如果我指定一个:

Partner PrincipalTitle = new Partner(Partner.SpecificTitle.Principal);

要输出值,我使用继承的Display()方法:

DefaultTitle.Display();

请帮助我理解我做错了什么。

6 个答案:

答案 0 :(得分:3)

基础Employee.Display()方法打印其title字段的值。 Director类定义new title字段,该字段隐藏(不覆盖)基本Employee.title字段。 PartnerDirector类适用于Director.title,与基本Employee.title字段无关。重构您的Director课程,以移除new title字段。

答案 1 :(得分:2)

问题是你使用这一行:

protected new string title = "Director";

new关键字隐藏了Employee的{​​{1}}定义。

如果那是你想要的,那不是真正的问题。当您将title执行路径调用回该方法的Partner.Display定义时,会出现问题。在Employee定义中,它使用隐藏的Employee字段。

当您在title课程中设置title时,您只在Partner课程中设置new title字段,而不是基类Director' Employee字段。

要解决此问题,请删除上述中提到的行。然后,您将希望使title构造函数看起来像这样。

Director

答案 2 :(得分:1)

看起来问题出现在Director类中,特别是以下行:

protected new string title = "Director";  // shadowing field works here

你真的不需要它,你也可能也想改变你的构造函数。继承人主任

public class Director : Employee
{
    //protected string title = "Director";  // shadowing field works here

    public int NumberOfProjectsManaged { get; set; }  // additional property

    public Director() : base() {
        NumberOfProjectsManaged = 0;
        title = "Director";
    } // constructor

    public override void Display()
    {
        base.Display();
        Console.WriteLine("Number of Projects Managed: {0}", NumberOfProjectsManaged);
    }
}

对于测试,我使用了这个:

Partner DefaultTitle = new Partner();
DefaultTitle.Display();
Partner PrincipalTitle = new Partner(Partner.SpecificTitle.Principal);
PrincipalTitle.Display();
Director director = new Director();
director.Display();

并获得以下输出:

Title: Partner
Number of Projects Managed: 0
Title: Principal
Number of Projects Managed: 0
Title: Director
Number of Projects Managed: 0

答案 3 :(得分:1)

为了满足您在Director类

中所有构造函数中定义标题的需要
public Director() : base() {
    // other stuffs
    this.title = "Director";
}

// other constuctors
public Director(object someparam) : this() {
    // do some stuff
}

因此,每次调用构造函数时,它都会冒泡到基础构造函数。

答案 4 :(得分:0)

您可以设置enum' SpecificTitle'来自合作伙伴课程的ouside。

public enum SpecificTitle
{
   Principal,
   Partner
};

并在Employee和Director类中使用标题类型作为' SpecificTitle'枚举

public abstract class Employee
{
   protected SpecificTitle title = "Employee";
   //others
}


 public class Director : Employee
 {
   protected SpecificTitle title = "Director";
   //others
 }

并将开关盒更换为:

switch (jobTitle)
{
  case SpecificTitle.Principal:
    this.title = SpecificTitle.Principal;
    break;
  case SpecificTitle.Partner:
  default:
    this.title = SpecificTitle.Partner;
    break;
}

或确定你应该用这一行替换开关盒

private void _setTitle(SpecificTitle jobTitle)
{
    this.title = jobTitle;
}

我没有测试过这个,但是这个逻辑可以和你一起使用。

答案 5 :(得分:0)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Partner DefaultTitle = new Partner();  // title = "Employee"
            DefaultTitle.Display();
            Console.ReadLine();
        }
    }

    public abstract class Employee
    {
        public virtual string title { get; set; }  // underlying field

      public string Title
      {
          get { return title; }
      }  // read-only property

      public Employee() { // do some stuff all children need 
          this.title = "Employee";
      }  // constructor

      public virtual void Display()
      {
        Console.WriteLine("Title: {0}", Title);
      }
    }


    public class Director : Employee
    {
      public override string title { get; set; }  // shadowing field works here

      public int NumberOfProjectsManaged { get; set; }  // additional property

      public Director() : base() {
          this.title = "Director";
      } // constructor

      public override void Display()
      {
        base.Display();
      }
    }


    public class Partner : Director
    {
      // there are more than two in the actual code, but this is a MWE
      public override string title { get; set; }
      public enum SpecificTitle
      {
        Principal,
        Partner
      };

      public Partner() : base() 
      {
        this._setTitle(SpecificTitle.Partner);  // defaults to Partner
      }

      public Partner(SpecificTitle jobTitle) 
      {
        this._setTitle(jobTitle);  // overloaded ctor allows user to specify
      }

      private void _setTitle(SpecificTitle jobTitle)
      {
        switch (jobTitle)
        {
          case SpecificTitle.Principal:
            this.title = "Principal";
            break;
          case SpecificTitle.Partner:
          default:
            this.title = "Partner";
            break;
        }
      }
    }
}

终于搞定了!对不起我的最后一个答案。我将基类设置为虚拟,因此任何子类都可以覆盖它的值。

C# virtual reference

robwaminal是正确的,在Partner类中设置标题只设置它的直接父级的标题Director