c # свойство get, заданное с разными типами

У меня есть такое перечисление и свойство.

        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 в строку

Как мне написать набор аксессуаров свойства?

ОБНОВЛЕНИЕ:

Я хотел, чтобы метод доступа get возвращал строку и устанавливал метод доступа для получения типа параметра Employee.Type. Я узнал, что это невозможно сделать в свойстве согласно спецификации C #. Мне нужно написать отдельные методы получения и установки.


person Timuçin    schedule 15.04.2011    source источник


Ответы (4)


Вместо этого используйте 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 - это просто методы.

person Yuriy Faktorovich    schedule 15.04.2011
comment
Нет ли возможности просто заполнить метод набора, не написав из него никакого кода? - person Timuçin; 15.04.2011
comment
Я бы не рекомендовал этого, потому что тогда вам придется выполнять какой-то синтаксический анализ строки для перечисления. Вы не знаете, будет ли строка поступать в правильном формате или это будет зарплата сотрудника. И что произойдет, если входящая строка вообще не является частью перечисления? Использование Enum ближе к статически типизированному контракту для использования пользователем. - person Yuriy Faktorovich; 15.04.2011
comment
ты прав. Ваше предложение - лучший вариант. Но предположим, что я пытаюсь разобрать его, как один из ответов ниже. Почему он все еще выдает ошибку «Невозможно неявно преобразовать тип« Employee.Type »в« строку »в конструкторе? - person Timuçin; 15.04.2011
comment
@Tim Скорее всего, потому что вы объявили свое свойство EmployeeType типа string и пытаетесь установить для него значение Enum. - person Yuriy Faktorovich; 15.04.2011
comment
Я думаю, что должен прояснить: я хочу, чтобы метод доступа get возвращал строку. Я хочу, чтобы набор доступа принял тип параметра Employee.Type. Разве это невозможно? - person Timuçin; 15.04.2011
comment
@Tim, что невозможно согласно C # Spec. - person Yuriy Faktorovich; 15.04.2011
comment
@ Юрий Факторович Спасибо за объяснение. - person Timuçin; 15.04.2011

Нравится:

EmployeeType = (Type)Enum.Parse(typeof(Type), value);
person Iain Ward    schedule 15.04.2011
comment
+1: Вот куда меня привели мои мысли. Я просто не использовал общий метод. - person Joel Etherton; 15.04.2011
comment
Это дает эту ошибку: неуниверсальный метод 'System.Enum.Parse (System.Type, string, bool)' не может использоваться с аргументами типа - person Timuçin; 15.04.2011
comment
@Joel Извините, это не общий, это была опечатка - person Iain Ward; 15.04.2011
comment
О, я не знал, что это не разрешает универсальный. Боже, это было бы здорово. Примечание для Microsoft: создайте универсальное расширение для Parse. - person Joel Etherton; 15.04.2011

Я рекомендую вам не использовать слово type, и вам нужно проанализировать перечисление:

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

Изменить:

Во-первых, я не могу повторить достаточно, чтобы не использовать слово «Тип» либо для перечисления, либо для строки для возврата свойства. Во-вторых, использование перечислений здесь с переключателем может привести к неприятностям, но значение по умолчанию может выручить вас.

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();
person Joel Etherton    schedule 15.04.2011
comment
+1 за рекомендацию не использовать слово Type, хотя ваше решение предполагает, что анализируемая строка совпадает с именем перечисления, которого нет в примере: Hourly vs.Hourly Employee. - person Rob Levine; 15.04.2011
comment
Это дает эту ошибку в конструкторе: невозможно неявно преобразовать тип 'Employee.Type' в 'строку' - person Timuçin; 15.04.2011
comment
@Tim: тогда ваше определение employeeType не должно быть равным Employee.Type. Где-то у вас конфликтующий тип. Можете ли вы внести правку, которая включает то, где вы объявляете переменную employeeType? - person Joel Etherton; 15.04.2011
comment
@ Тим: Я заметил еще пару вещей, поэтому опубликую правку. - person Joel Etherton; 15.04.2011
comment
@Joel Etherton: Спасибо, но я хотел, чтобы аксессор get возвращал строку и установил аксессор, чтобы он принимал тип параметра Employee.Type. @Yuriy Faktorovich говорит, что это невозможно согласно спецификации C #. - person Timuçin; 15.04.2011
comment
@ Тим: Это невозможно. Честно говоря, я не могу придумать рациональной причины, по которой вы бы захотели. - person Joel Etherton; 15.04.2011

В идеале у вас все еще должен быть частный член, который вы можете установить / получить, к которому свойство может прикрепляться. Оттуда вы можете сделать другой метод получения версии, удобочитаемой / отформатированной. например

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, потому что нет действительного перечисления, соответствующего вводу.

EDITv2 Мне действительно нравится @ Yuriy's лучше использовать DescriptionAttribute. Сохраняйте шрифтовую структуру, но делайте ее разборчивой при печати.

person Brad Christie    schedule 15.04.2011
comment
Нет возможности сделать это только в заданном методе? - person Timuçin; 15.04.2011
comment
@Tim: суть перечисления для облегчения использования жестких строк для значений. Вы можете проанализировать value и найти набор предопределенных значений и установить свою переменную employeeType, но это кажется запутанным по сравнению с простой ссылкой на значения перечисления. - person Brad Christie; 15.04.2011