使用枚举值表示两个枚举值

4

想象一下场景。

public enum SaveStates
{
    Saved,               //Represents a successful save.
    SavedWithChanges,    //Represents a successful save, where records were modified
    SavedWithoutChanges  //Represents a successful save, but no records were modified
}

在这个场景中,如果枚举类型为 SavedWithChanges 或者 SavedWithoutChanges ,那么可以将其视为 Saved
因此,如果我有一个像这样的变量:
SaveStates lastState = SaveStates.SavedWithoutChanges;

我希望能够做类似于这样的事情:

if (lastState == SaveStates.Saved)
{
    //The state is saved, do something awesome.
}

我当然可以做到这一点:

if (lastState == SaveStates.SavedWithChanges || lastState == SaveStates.SavedWithoutChanges)
{
    ...

然而,这有点繁琐,我不能假设另一个开发人员知道如何正确地使用枚举。
由于可能存在一种情况,即在保存事件中没有进行任何更改时,我们可能希望执行某些特定操作,因此每个枚举都是必需的。
我可以接受替代设计想法。

1
我认为其他开发人员不会理解这个。在我看来,这比使用标志属性更清晰。 - Tim Schmelter
你的枚举类型应该有一个未保存的值,否则为什么要检查它是否已保存?你只需要使用 Enum.IsDefined - juharr
6个回答

5
如果您担心的是代码可读性,您可以使用以下类似的扩展方法:
public static class SaveStatesExtension
{
    public static bool IsSavedState(this SaveStates state) {
        return state == SaveStates.SavedWithChanges || 
               state == SaveStates.SavedWithoutChanges;
    }
}

那么你的使用示例将变为:
if (lastState.IsSavedState())
{
    //The state is saved, do something awesome.
}

当然,在这种情况下,枚举中的Saved成员将不再需要。


3
您可以按照以下方式实现,参考我在问题下发布的链接示例,但使用非排他标志值。请注意,SavedWithChangesSavedWithoutChanges都包含位1,分配给Saved
[Flags]
public enum SaveStates
{
    Saved = 1,
    SavedWithChanges = 3,
    SavedWithoutChanges = 5
}

if ((lastState & SaveStates.Saved) == SaveStates.Saved)
{

}

然而,对于其他开发人员来说,这可能相当不直观 - 通常不会以此方式使用标志枚举。因此,明确说明所有条件和所有枚举值可能更易读。由Konamiman提出的非常好的想法

public static bool IsSaved(SaveStates state)
{
    return state == SaveStates.SavedWithChanges
        || state == SaveStates.SavedWithoutChanges;
}

结合了两个世界的优点:满足最小惊奇原则,同时又简洁易读。

3
如果您要使用Flags枚举来完成此操作,建议您使其自我记录。
[Flags]
public enum SaveStates
{
    Saved = 1,
    WithChanges = 2,
    SavedWithoutChanges = Saved, // a bit pointless! Its the same as Saved
    SavedWithChanges = Saved | WithChanges  // has value "3"
}

然后,根据其他答案的说法

if ((lastState & SaveStates.Saved) == SaveStates.Saved)
{

}

是我还是你完全弄错了这些标志。在使用标志时,应该使用所有组件。并将 Saved 设为 Saved = With | Without - kevintjuh93
1
点赞这个答案。对我来说,更直观的是“已保存”和“已更改”是两个不同的事情。将它们放入一个枚举中会导致部分混淆。我可能会更进一步地为保存状态和更改状态各设置一个属性。为什么这样做?当您保存带有更改的内容,然后进行更改并再次保存时,您必须评估是否已进行了先前的更改,以确定要选择的新枚举。其他所有内容都可以包装成扩展方法,根据需要设置/获取这些值。 - Trevor Ash
@kevintjuh93 - 是你 ;) - Jamiec
@Jamiec 但说真的... Saved 同时包含了 有和没有 更改。所以应该反过来。 - kevintjuh93
1
@kevintjuh93,这个方案是否好取决于OP,我同意它可能不是表示某些东西的保存状态的最佳方式。这个答案试图表明,虽然可以使用“Flags”枚举来实现(如之前回答中所述),但也有一种方法可以以相同的方式实现,但在代码中添加一定程度的自我文档化。 - Jamiec

1

改变你的枚举,怎么样?

public enum SaveStates
{
    NotSaved,               //Represents "not saved" state
    SavedWithChanges,    //Represents a successful save, where records were modified
    SavedWithoutChanges  //Represents a successful save, but no records were modified
}

在这种情况下,您可以使用否定来达到您所说的目的:
if (lastState != SaveStates.NotSaved)
{
    //The state is saved, do something awesome.
}

此外,它提供了一个枚举值,可以用作“默认”值,这被认为是一种良好的、符合“清洁代码”原则的做法。


0
我更喜欢这个:
SaveStates[] savedWithOrWithoutChanges = { SaveStates.SavedWithChanges, SaveStates.SavedWithoutChanges };
if (savedWithOrWithoutChanges.Contains(lastStat))
{
    ...
}

这非常直观,每个开发者都能理解。


0

不妨使用两个 bool 值来代替一个枚举表示两种状态。一个用于指示是否已保存,另一个用于指示是否“有更改”。如果第一个值为 false,则忽略第二个值。

private bool saved;

private bool withChanges;

public void SomeMethod()
{
    if (saved)
    {
        Console.WriteLine("Saved");

        if (withChanges)
        {
            Console.WriteLine("With Changes");
        }
        else
        {
            Console.WriteLine("Without Changes");
        }
    }
    else
    {
        Console.WriteLine("Not saved");
    }
}

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