C#属性的Get和Set方法可以使用不同类型

7

我有一个枚举和一个属性。

        public enum Type
        {
            Hourly = 1,
            Salary = 2,
            None = 3
        };


        public string EmployeeType
        {
            get
            {
                string type;
                switch (employeeType)
                {
                    case Type.Hourly:
                        type = "Hourly Employee";
                        break;
                    case Type.Salary:
                        type = "Salary Employee";
                        break;
                    default:
                        type = "None";
                        break;
                }
                return type;
            }

            // **EDIT:**
            // Now I am trying to parse the string as enum Type.
            // But Constructor still waits a string to set EmployeeType.
            set
            {
                employeeType = (Type)Enum.Parse(typeof(Type), value);
            }
        }

这是我的课程:
public class Employee
{
     private Type employeeType;
}

我希望您能创建这样的构造函数:
Employee(Employee.Type type) 
{
      EmployeeType = type;
}

编辑:

无法将类型“Payroll.Employee.Type”隐式转换为“string”

我该如何编写属性的set访问器?

更新:

我希望get访问器返回字符串,而set访问器则接受参数类型Employee.Type。根据C#规范,无法在属性中实现此操作。我必须编写单独的getter和setter方法。

4个回答

12

使用 DescriptionAttribute 替代。

public enum Type
{
    [Description("Hourly Employee")]
    Hourly = 1,
    [Description("Salary Employee")]
    Salary = 2,
    [Description("None")]
    None = 3
};
那么你只需要有一个
public Type EmployeeType {get; set;}

属性。如果有人想把它写出来,他们可以得到描述。我还会称其为Type而不是EmployeeType,因为调用myEmployee.EmployeeType听起来多余。你的另一个选择可能是取消属性并拥有两种方法。

public string GetEmployeeType() { //your switch statement }
public void SetEmployeeType(EmployeeType type)
{
    _type = type;
}

虽然不如属性优雅,但可以快速完成工作。还要记住,在IL中,属性只是方法。


你是对的。你的建议是更好的选择。但是假设我正在尝试像下面的一个答案一样解析它。为什么在构造函数上仍然会出现“无法隐式转换类型'Employee.Type'到'string'”的错误? - Timuçin
@Tim 可能是因为你将 EmployeeType 属性声明为字符串类型,而试图将其设置为枚举类型。 - Yuriy Faktorovich
1
我想我必须澄清一下:我希望get访问器返回字符串。 我希望set访问器接受参数类型为Employee.Type。这不可能吗? - Timuçin
2
@Tim,根据C#规范,这是不可能的。 - Yuriy Faktorovich
@Yuriy Faktorovich 谢谢您的解释。 - Timuçin
显示剩余2条评论

4

像这样:

EmployeeType = (Type)Enum.Parse(typeof(Type), value);

+1:这就是我的想法。我只是没有使用通用方法。 - Joel Etherton
它给出了这个错误:非泛型方法'System.Enum.Parse(System.Type, string, bool)'无法使用类型参数。 - Timuçin
@Joel 抱歉,这不是通用的,那是个打字错误。 - Iain Ward
哦,我不知道它不允许泛型。天啊,那太好了。给微软的建议:为Parse制作一个泛型扩展。 - Joel Etherton

3

我建议您不要使用"type"这个词,而是需要解析枚举:

set
{
    employeeType = (Type)Enum.Parse(typeof(Type), value);
}

编辑:

首先,无论是枚举还是返回属性的字符串,请勿使用“Type”这个词。其次,在此处使用switch语句可能会让你陷入麻烦,但默认情况下可能会帮你解决问题。

public enum WorkType
{
    Hourly = 1,
    Salary = 2,
    None = 3
};

// Initialize this to prevent craziness
private WorkType employeeType = WorkType.None;
public string EmployeeType
{
    get
    {
        // I'm not sure why you want to return a string
        // in this property but whatevs.
        // First make sure that you have a valid enum
        if ((int)employeeType > 3 || (int)employeeType < 1)
            employeeType = WorkType.None;
        return employeeType.ToString();   // Don't need a switch, just call ToString()
        }

        set
        {
            // This might be better served with a TryParse. This will
            // be more fault tolerant if someone using your class passes
            // in an invalid WorkType.
            if(!TryParse(typeof(WorkType), value, out employeeType))
                employeeType = WorkType.None;
        }
    }
}

我猜测你在转换时遇到的问题是使用了非字符串的赋值,例如:
WorkType someType = WorkType.None;
this.EmployeeType = someType;   // Exception is here

这是一个无效的情况,因为someType是一个类型而EmployeeType(值)是一个字符串。 要修复此问题,您需要分配如下:

this.EmployeeType = someType.ToString();

所有这些都可以归结为相当愚蠢,因为它可以通过如下简单的方式来完成:
public enum WorkType
{
    Hourly = 1,
    Salary = 2,
    None = 3
};

public WorkType EmployeeType { get; set; }
// Any time you want to access the value of EmployeeType as a string you would
// simply use the following line:
// EmployeeType.ToString();

+1 建议不要使用“类型”这个词,尽管您的解决方案假设被解析的字符串与枚举名称相同,但在示例中并非如此:按小时计费 vs. 按小时计费员工。 - Rob Levine
构造函数出现了以下错误:无法将类型“Employee.Type”隐式转换为“string”。 - Timuçin
@Tim:那么你对employeeType的定义一定不是设置为Employee.Type。你的某个地方存在类型冲突。你能否提供一个编辑,其中包括你声明变量employeeType的位置? - Joel Etherton
@Tim:我注意到了一些其他的事情,所以我会发布一个编辑。 - Joel Etherton
@Joel Etherton:谢谢你,但我想让get访问器返回字符串,并让set访问器接受参数类型Employee.Type。 @Yuriy Faktorovich说根据C#规范这是不可能的。 - Timuçin
@Tim:做那是不可能的。说实话,我想不出你为什么想要这么做的任何理性原因。 - Joel Etherton

-1
理想情况下,您仍应该拥有一个可以设置/获取的私有成员,以便属性可以附加到该成员。从那里,您可以创建另一个方法来获取“人类可读/格式化”的版本。例如:
public enum EmployeeType
{
  Hourly = 1,
  Salary = 2,
  None = 3
}

private EmployeeType _EmployeeType;

public EmployeeType EmployeeType
{
  get { return this._EmployeeType; }
  set { this._EmployeeType = value; }
}

然后你有一个方法来返回格式化的版本

public String EmployeeType()
{
  switch (this._EmployeeType)
  {
    case EmployeeType.Hourly:
      return "Hourly Employee";
    case EmployeeType.Salary:
      return "Salary Employee";
    default:
      return "None";
  }
}

或者这就是我会做的方式。否则,枚举就没有意义,你应该只使用字符串并验证输入/输出是否落在预选的有效值范围内。

编辑 我之所以推荐这个方法,是因为使用字符串输入并尝试将其与枚举名称对齐(正如其他人所建议的那样)在我看来似乎有缺陷。特别是从“按小时计算”转换为“按小时计算的员工”。(obj).EmployeeType = "Hourly Employee"无法使用Enum.Parse,因为没有与输入匹配的有效枚举。

编辑v2 我实际上更喜欢@Yuriy's使用DescriptionAttribute的方法。保持类型结构化,但在打印时使其易读。


有没有办法只在设置方法中完成这个操作? - Timuçin
@Tim:枚举的目的在于减轻使用“硬编码字符串”来表示值。你可以解析value并查找一组预定义的值,并设置你的employeeType变量,但这似乎比直接引用枚举值更加复杂。 - Brad Christie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接