Флаг Enum и взаимоисключающий Enum с перекрывающимся значением - PullRequest
4 голосов
/ 12 октября 2010

У меня есть модель, которая должна находиться в одном из следующих взаимоисключающих состояний: Новый , В процессе или Закрыт .

Приложение позволяет пользователю сохранять записи и затем извлекать их, предоставляя список соответствующих состояний.

Я унаследовал базу данных SQL, где состояние хранится как целое число, представляющее побитовые флаги. Я должен вызвать процедуру, которая выполняет сопоставление с побитовой операцией:

CREATE PROCEDURE SearchByState
    @MatchingStates       int
AS
BEGIN
    SELECT Id, State
    FROM Records
    WHERE @MatchingStates & State > 0
END;
GO

Это все нормально для меня.

Теперь, в реализации C #, совершенно очевидно, что я должен определить флаги для представления комбинации соответствующих состояний в запросе:

[Flags]
public enum States
{
    None = 0x0,
    New= 0x1,
    InProgress = 0x2,
    Closed = 0x4,
    All = New | InProgress | Closed
}

Проблема заключается в том, что модель записи должна иметь свойство, представляющее одно состояние.

Вопрос в том, каким должен быть тип государственного свойства модели этой записи:

1) Просто используйте флаги перечисления:

public class Record
{
    public int Id { get; set; }

    // Must ensure the value is equal to one of
    // States.New, States.InProgress, or States.Closed
    public States State { get; set; }
}

2) Определите новый тип перечисления для взаимоисключающего состояния:

public enum State
{
    New,
    InProgress,
    Closed
}

public class Record
{
    public int Id { get; set; }

    // Must be stored as the value of one of 
    // States.New, States.InProgress, or States.Closed
    public State State { get; set; }
}

Недостаток # 1 является семантическим: перечисление States представляет собой комбинацию состояний, а не одно состояние.

Недостаток # 2 практичен: при сохранении состояния я должен определить базовое значение для хранения.

Можете ли вы придумать способ представить все это, минимизируя эти недостатки?

Ответы [ 2 ]

4 голосов
/ 12 октября 2010

Я бы оставил это как одно перечисление без флагов.

Когда вы передаете это своей процедуре, вы можете построить целое число из перечисления с помощью побитового или (|) или даже просто добавить значения (приведенные к int). Я бы постарался не «сломать» вашу логику, чтобы заставить работать один устаревший запрос, и вместо этого переработал код, вызывающий запрос, для обработки необычных требований.

Это сохраняет код чистым везде. «State» в вашем случае не должно быть перечислением флага - существует только одно возможное состояние.

1 голос
/ 12 октября 2010

Я бы выбрал вариант # 2, а затем изменил бы ваши инструкции Get / Set, чтобы каждый раз определять базовое значение. Таким образом, это делается для вас каждый раз, когда вы вызываете свойства. Запишите его один раз, и все готово.

...