C# 使用字符串而不是枚举?

C# 使用字符串而不是枚举?,c#,methods,code-design,C#,Methods,Code Design,使用字符串与枚举进行比较是否常见?至少,字符串应该在某个地方声明为常量(或者可能是只读字段),而不是分散在代码中。但是,关于何时使用enum,这看起来像教科书中的示例 public enum ObjectType { UAV, Entity, // and so on } 至少,字符串应该在某个地方声明为常量(或者可能是readonly字段),而不是通过代码分散。但是,关于何时使用enum,这看起来像教科书中的示例 public enum ObjectType { UA

使用字符串与枚举进行比较是否常见?

至少,字符串应该在某个地方声明为常量(或者可能是
只读
字段),而不是分散在代码中。但是,关于何时使用
enum
,这看起来像教科书中的示例

public enum ObjectType
{
   UAV,
   Entity,
   // and so on
}

至少,字符串应该在某个地方声明为常量(或者可能是
readonly
字段),而不是通过代码分散。但是,关于何时使用
enum
,这看起来像教科书中的示例

public enum ObjectType
{
   UAV,
   Entity,
   // and so on
}

我知道您的上下文,但作为第一步,您可以通过以下方式重构:

步骤1

if (typeOfObject == "UAV")
{
    DoSomeWork(_stkObjectRootToIsolateForUavs);
}
else if (typeOfObject == "Entity")
{
    DoSomeWork(_stkObjectRootToIsolateForEntities);
}

private void DoSomeWork(IAgStkObject agStkObject)
{
    IAgStkObject stkObject = agStkObject.CurrentScenario.Children[stkObjectName];
    IAgDataProviderGroup group = (IAgDataProviderGroup)stkUavObject.DataProviders["Heading"];
    IAgDataProvider provider = (IAgDataProvider)group.Group["Fixed"];
    IAgDrResult result = ((IAgDataPrvTimeVar)provider).ExecSingle(_stkObjectRootToIsolateForUavs.CurrentTime);

    stkObjectHeadingAndVelocity[0] = (double)result.DataSets[1].GetValues().GetValue(0);
    stkObjectHeadingAndVelocity[1] = (double)result.DataSets[4].GetValues().GetValue(0);
}

然后考虑再塑化与开关的关系:

步骤2

switch (typeOfObject)
{
    case "UAV":
        DoSomeWork(_stkObjectRootToIsolateForUavs);
        break; 
    case "Entity":
        DoSomeWork(_stkObjectRootToIsolateForEntities);
        break;
    default:
        throw new NotImplementedException():
}

使用枚举时,这可能会更好。

我知道您的上下文,但作为第一步,您可以通过以下方式重构:

步骤1

if (typeOfObject == "UAV")
{
    DoSomeWork(_stkObjectRootToIsolateForUavs);
}
else if (typeOfObject == "Entity")
{
    DoSomeWork(_stkObjectRootToIsolateForEntities);
}

private void DoSomeWork(IAgStkObject agStkObject)
{
    IAgStkObject stkObject = agStkObject.CurrentScenario.Children[stkObjectName];
    IAgDataProviderGroup group = (IAgDataProviderGroup)stkUavObject.DataProviders["Heading"];
    IAgDataProvider provider = (IAgDataProvider)group.Group["Fixed"];
    IAgDrResult result = ((IAgDataPrvTimeVar)provider).ExecSingle(_stkObjectRootToIsolateForUavs.CurrentTime);

    stkObjectHeadingAndVelocity[0] = (double)result.DataSets[1].GetValues().GetValue(0);
    stkObjectHeadingAndVelocity[1] = (double)result.DataSets[4].GetValues().GetValue(0);
}

然后考虑再塑化与开关的关系:

步骤2

switch (typeOfObject)
{
    case "UAV":
        DoSomeWork(_stkObjectRootToIsolateForUavs);
        break; 
    case "Entity":
        DoSomeWork(_stkObjectRootToIsolateForEntities);
        break;
    default:
        throw new NotImplementedException():
}

当使用枚举时,这可能会更好。

我同意@Frederik的观点,即这似乎是使用枚举的完美案例,但这可能是应用程序中唯一可以得到的东西是字符串。在这种情况下,您的示例完全正确


哦,是的-请确保在一个地方定义了字符串常量,最好是一个配置文件,这样如果它们更改了其他应用程序,您就不必重新编译自己的应用程序。

我同意@Frederik的观点,这似乎是使用枚举的最佳情况,但您可以从应用程序中获得的唯一东西可能是字符串。在这种情况下,您的示例完全正确


哦,是的-确保在一个地方定义了字符串常量,最好是一个配置文件,这样如果它们更改了其他应用程序,您就不必重新编译自己的应用程序。

使用带位标志的枚举:

[Flags]
public enum MyFlags
{
    SomeFlag = 0x1, // 001
    OtherFlag = 0x2,// 010
    ThirdFlag = 0x4 // 100
}

var firstObject = MyFlags.SomeFlag;
var secondObject = MyFlags.SomeFlag | MyFlags.OtherFlag;

if(((int)secondObject & MyFlags.SomeFlag) != 0) 
{
    // true
}

if(((int)secondObject & MyFlags.OtherFlag) != 0) 
{
    // true
}

if(((int)firstObject & MyFlags.SomeFlag) != 0) 
{
    // true
}

if(((int)firstObject & MyFlags.OtherFlag) != 0) 
{
    // false
}

会很有帮助。

使用带有位标志的枚举:

[Flags]
public enum MyFlags
{
    SomeFlag = 0x1, // 001
    OtherFlag = 0x2,// 010
    ThirdFlag = 0x4 // 100
}

var firstObject = MyFlags.SomeFlag;
var secondObject = MyFlags.SomeFlag | MyFlags.OtherFlag;

if(((int)secondObject & MyFlags.SomeFlag) != 0) 
{
    // true
}

if(((int)secondObject & MyFlags.OtherFlag) != 0) 
{
    // true
}

if(((int)firstObject & MyFlags.SomeFlag) != 0) 
{
    // true
}

if(((int)firstObject & MyFlags.OtherFlag) != 0) 
{
    // false
}

会很有帮助。

要补充@Restuta的答案,我会使用

IDictionary<MyEnumifiedString, Action<IAgStkObject>> 
IDictionary

为了消除这个if。

为了增加@Restuta的答案,我会使用

IDictionary<MyEnumifiedString, Action<IAgStkObject>> 
IDictionary

为了摆脱这个if。

关于您的第一个问题,我将始终使用定义的类型来存储字符串,以便在需要时有一个位置进行更改

因此,对于你的例子,我有以下几点

public sealed class RootTypes
{
    public const string Entity = "entity";
    public const string UAV = "uav";
}
然后,您的代码将更新到此

    typeOfObject = typeOfObject.ToLower();
    if (typeOfObject == RootTypes.UAV)
    {
        stkUavObject = _stkObjectRootToIsolateForUavs.CurrentScenario.Children[stkObjectName];
        var group = (IAgDataProviderGroup) stkUavObject.DataProviders["Heading"];
        var provider = (IAgDataProvider) group.Group["Fixed"];
        IAgDrResult result = ((IAgDataPrvTimeVar) provider).ExecSingle(_stkObjectRootToIsolateForUavs.CurrentTime);
        stkObjectHeadingAndVelocity[0] = (double) result.DataSets[1].GetValues().GetValue(0);
        stkObjectHeadingAndVelocity[1] = (double) result.DataSets[4].GetValues().GetValue(0);
    }
    else if (typeOfObject == RootTypes.Entity)
    {
        IAgStkObject stkEntityObject = _stkObjectRootToIsolateForEntities.CurrentScenario.Children[stkObjectName];
        var group = (IAgDataProviderGroup) stkEntityObject.DataProviders["Heading"];
        var provider = (IAgDataProvider) group.Group["Fixed"];
        IAgDrResult result = ((IAgDataPrvTimeVar) provider).ExecSingle(_stkObjectRootToIsolateForEntities.CurrentTime);
        stkObjectHeadingAndVelocity[0] = (double) result.DataSets[1].GetValues().GetValue(0);
        stkObjectHeadingAndVelocity[1] = (double) result.DataSets[4].GetValues().GetValue(0);
    }

Restuta已经解决了代码冗余问题。关于第一个问题,我将始终使用已定义的类型来存储字符串,以便在需要时有一个位置进行更改

因此,对于你的例子,我有以下几点

public sealed class RootTypes
{
    public const string Entity = "entity";
    public const string UAV = "uav";
}
然后,您的代码将更新到此

    typeOfObject = typeOfObject.ToLower();
    if (typeOfObject == RootTypes.UAV)
    {
        stkUavObject = _stkObjectRootToIsolateForUavs.CurrentScenario.Children[stkObjectName];
        var group = (IAgDataProviderGroup) stkUavObject.DataProviders["Heading"];
        var provider = (IAgDataProvider) group.Group["Fixed"];
        IAgDrResult result = ((IAgDataPrvTimeVar) provider).ExecSingle(_stkObjectRootToIsolateForUavs.CurrentTime);
        stkObjectHeadingAndVelocity[0] = (double) result.DataSets[1].GetValues().GetValue(0);
        stkObjectHeadingAndVelocity[1] = (double) result.DataSets[4].GetValues().GetValue(0);
    }
    else if (typeOfObject == RootTypes.Entity)
    {
        IAgStkObject stkEntityObject = _stkObjectRootToIsolateForEntities.CurrentScenario.Children[stkObjectName];
        var group = (IAgDataProviderGroup) stkEntityObject.DataProviders["Heading"];
        var provider = (IAgDataProvider) group.Group["Fixed"];
        IAgDrResult result = ((IAgDataPrvTimeVar) provider).ExecSingle(_stkObjectRootToIsolateForEntities.CurrentTime);
        stkObjectHeadingAndVelocity[0] = (double) result.DataSets[1].GetValues().GetValue(0);
        stkObjectHeadingAndVelocity[1] = (double) result.DataSets[4].GetValues().GetValue(0);
    }

Restuta已经解决了代码冗余的问题。

@Fredrik Mörk,这回答了核心问题——如何减少复制?@WulfgarPro:你可以用它来研究@Felice的想法。我不同意抽象工厂。这里怎么用?也许你指的是简单工厂,或者仅仅是工厂方法?根据OP,他似乎只有字符串可以使用,这基本上排除了枚举,除非你想开始使用Enum.GetName()等等。还是我遗漏了什么?@Restuta:在本例中,我认为您在回答中建议的
DoSomeWork
方法已经足够了,因为所呈现的两个案例是以相同的方式处理的。@Fredrik Mörk,这回答了一个核心问题——如何减少复制?@WulfgarPro:你可以和我一起研究@Felice的想法。我不同意抽象工厂。这里怎么用?也许你指的是简单工厂,或者仅仅是工厂方法?根据OP,他似乎只有字符串可以使用,这基本上排除了枚举,除非你想开始使用Enum.GetName()RESUTA:在这种情况下,我认为在您的答案中建议的<代码> DoSomeWork <代码>方法已经足够了,因为这两个呈现的情况都是以相同的方式来执行的。步骤2a:如果您选择了2个以上的选项,考虑用虚拟方法替换I/Twitter。请参阅步骤2a:如果您选择了2个选项,可以考虑用虚拟方法替换I/Twitter。See ToLower()有点笨重,并非所有语言都100%支持它。最好使用string.Equals(string1、string2、StringComparison.OrdinalIgnoreCase)获得大小写不变的Equals。ToLower()有点笨重,并非所有语言都100%支持。最好使用string.Equals(string1、string2、StringComparison.OrdinalIgnoreCase)来获得大小写不变的Equals。位标志最终会咬到您。-当您声明另一个标志,但希望它介于0x1和0x2之间时会发生什么?位标志最终会咬到您。-如果声明另一个标志,但希望它介于0x1和0x2之间,会发生什么情况?