【问题标题】:How to implement C# enum for enumerated char(1) database field?如何为枚举的 char(1) 数据库字段实现 C# 枚举?
【发布时间】:2009-07-24 21:14:33
【问题描述】:

好的,所以我有一个 char(1) 类型的数据库字段,其中包含少量可能的状态代码(例如,'F'= Failure、'U'=Unknown 等)。我想要一个对应于这些状态的 C# 枚举类。我能做到:

public enum StatusCode : byte {
    Unknown = (byte) 'U',
    Failure = (byte) 'F',
    // etc.
}

到目前为止一切顺利。但是在从数据库返回的DataTable中,列值是System.Data.SqlTypes.SqlString实例。从 C# 字符串(甚至 C# 字符)转换为 C# 字节(因为 C# 字符实际上是 UTF-16 代码点)显然存在一些问题。但在这种情况下,我知道这些值被限制在一个小集合中,如果这个集合之外的值通过,代码应该抛出异常。

考虑到这一点,最好的方法是什么?从 SqlString 转换为字节是否安全? Convert.ToByte() 会更好吗?简单地使用 switch/case 构造将值交叉传递到枚举中会更好吗?

我正在寻找执行此操作的“最佳”方法,不仅是为了获得正确的结果,而且是为了代码的清晰性。我想我也可以只使用一些常量,例如

public const char UnknownStatus = 'U';
public const char FailureStatus = 'F';

但如果可能的话,我宁愿使用枚举。有什么想法吗?

编辑:为了阐明我想对此做什么,我希望在我的代码中经常使用这些值。例如,我希望能够执行以下操作:

public void DoSomething(StatusCode currentStatus) {
    if(currentStatus == StatusCode.Failure) {
        throw new SomeException();
    }

    switch(currentStatus) {
        case StatusCode.Unknown:
            // do something
            break;
    }
}

等等。我特别想避免这样的事情:

public void DoSomething(char currentStatus) {
    if(currentStatus == 'F') {
        // do something
    }
}

因为在这种情况下,我到处都在使用相当于“幻数”的东西。特别是,这将使迁移到其他一些状态标记系统几乎是不可能的。这有意义吗?

【问题讨论】:

标签: c# ascii byte


【解决方案1】:

也许是一个“常量”对象?

public sealed class StatusCode {
    private char value;

    public static readonly StatusCode Unknown = new StatusCode('U');
    public static readonly StatusCode Failure = new StatusCode('F');

    private StatusCode(char v) {
        value = v;
    }

    public override string ToString() {
        return value.ToString();
    }

}

然后,稍后在您的代码中,您可以像枚举一样使用它:StatusCode.Unknown。您还可以提供一个内部方法来将接收到的值“解析”到 StatusCode 的对象中。

【讨论】:

  • 您还应该提供隐式相等来为某些值提供正确的比较...
  • 好的,我想这就是我要走的路线。不幸的是,案例陈述仍然不能像我想要的那样工作,但至少其他一切都可以。 (就像旧式 Java 枚举模式一样!)
【解决方案2】:

跳到编辑你有没有试过这个(你已经检查并评论了它不起作用):

public enum StatusCode : char
{
    Failure = 'F',
    Unknown = 'U',
    ...
}

编辑 - 正确的解决方案
或者这个(甚至可以尝试使用结构):

public sealed class StatusCode
{
    public static readonly char Failure = 'F';
    public static readonly char Unknown = 'U';
    ...
    public char Value { get; set; }
}

您提供的代码会这样工作:

public void DoSomething(StatusCode currentStatus) {
    if(currentStatus.Value == StatusCode.Failure) {
        throw new SomeException();
    }

    switch(currentStatus.Value) {
        case StatusCode.Unknown:
            // do something
            break;
    }
}

如果您不喜欢使用 Value 属性,您始终可以在 StatusCodechar 类型之间实现隐式相等运算符。在这种情况下,您的代码不会有任何改变。

【讨论】:

  • 不好:编译器给出:错误 994 类型 byte、sbyte、short、ushort、int、uint、long 或 ulong 期望
  • ^^ 我差点错过了! :D
  • 这仅以 byte 而不是 char 作为基本类型;和 (char)'F' 等。
【解决方案3】:

如果您使用的是 .NET 2.0 或更高版本,则可以使用通用字典来实现:

Dictionary<char,string> statusCode = new Dictionary<char,string>();
statusCode.Add('U', "Unknown");
statusCode.Add('F', "Failure");

或者:

Dictionary<char,StatusCode> statusCode = new Dictionary<char,StatusCode>();
statusCode.Add('U', StatusCode.Unknown);
statusCode.Add('F', StatusCode.Failure);

你可以像这样访问给定代码的字符串表示:

string value = statusCode['A'];

StatusCode myCode = statusCode['A'];

等等。您必须从数据库值或某种配置文件或其他东西中填充该字典。

马克

【讨论】:

    【解决方案4】:

    这样的东西对你有用吗?

    public Enum StatusCode : int{
       [StringValue("U")]
       Unknown =0,
       [StringValue["F"]
       Failuer=1
    }
    

    【讨论】:

    【解决方案5】:

    如果您有一个名为 StatusCode 的表,其中包含一个整数主键,那么您可以将其用作您的标识符并将其挂钩到您的逻辑中。在这种情况下,枚举将是最好的使用方法。虽然我不确定这对你是否可行。

    【讨论】:

      【解决方案6】:

      一种选择是使用与数据库中的值相同的名称来设置枚举,例如:

      enum StatusCode
      {
          /// <summary>Unknown</summary>
          U = 0,
          /// <summary>Failure</summary>
          F,
          /// <summary>Etc</summary>
          E
      }
      

      然后使用静态方法将char值转换为枚举值

          private StatusCode CharToEnum(string statusCodeChar)
          {
              foreach (FieldInfo fi in typeof(StatusCode).GetFields())
              {
                  if (fi.Name == statusCodeChar) return (StatusCode)fi.GetValue(null);
              }
      
              return StatusCode.U;
          }
      

      【讨论】:

        【解决方案7】:

        又短又甜,我的男人.. 做你需要的一切。您不需要使用 enum,因为您不需要它来为可能的状态分配内部值,您已经知道状态的值。

        public sealed class StatusCode
        {
            public const string Unknown= "U";
            public const string Failure= "F";
            public const string Success= "S";
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-05-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多