zoukankan      html  css  js  c++  java
  • 枚举——你是那温柔的陷阱吗

          最近在园子里看了两篇关于枚举的文章《小心枚举陷阱》和《温柔的枚举陷阱》,说的都是一个问题:前台绑定枚举,数据库中存储枚举的值,当枚举更新后,数据库中的值却没有更新,于是引起了一堆数据不对应的问题。

      在系统中,我们肯定都遇到过用枚举来储存数据的情况,如下图,需要显示的是学历,但学历这东西毕竟不是经常改,所以就用枚举吧,放在数据库中,还要新建一张表,还要左联,太麻烦。

    如是就有了以下代码:

    public enum EStueType { 小学, 中学, 大学, } 

       然后数据库中存储的就是0、1、2,用来分别表示小学、中学、大学。

      但后来,新的需求来了,需要将中学变为初中和高中。有人想当然,直接将“中学”改成“初中”,然后再在“初中”和“大学”之间加一个“高中”,编译无误,OK,挂到服务器上了。

    后来客户反应,噫?我以前不是填的大学吗?现在怎么变成高中生了啊?管理员拿个VS编译半天,终于发现,原来添加了一个“高中”后,“高中”的值变为2 了,也就是说数据库中原来的所有学历为2(以前表示的是大学生),现在都变成高中生了。哎,都是这温柔的枚举惹的祸啊,于是开始摈弃枚举。

      解决这个问题常用的做法有两种:

      1.新建一张表,专门用来存储学历

      2.接着用那温柔的枚举。

      

      第一种方法很好的解决了这个问题,但问题在于会在数据库中新建表,并且是一张更新不多的表,另一个问题是如果数据量大时,左联会影响性能。

      第二种方法就需要我们很好的解决枚举的问题了,下面我就讲我用枚举时的做法。

      

      用枚举时我们也有两种做法:第一:将枚举显示赋值:如下:

        public enum EStueType
            {
                小学=0,
                中学=1,
                大学=2,
            }

      OK,你要新加一个高中对吧,难不到我:

       public enum EStueType
            {
                小学=0,
                 初中=1,

                   高中=3,
                大学=2,
            }
       新问题:dbo查数据:select * from [表名],然后发现用户的学历这儿,一堆0123,想当然的他认为

        0代表小学

        1代表初中

        2代表高中

        3代表大学

       OK,他接下的操作就极具危险性了:他要对所有的大学生进行一次“婚前性教育培训课”,结果...........

      

      于是,我们想着,要不我们数据库中直接存储枚名称,而不是值,也就是表中学历字段直接存储如“大学”。  

      嗯,这个办法不错,问题都解决了。

      但好像我们学编程的第一节课老师就说了:不要用中文。有两个原因:

      1.中文占用更多的数据空间

      2.中文编程总让人感觉不是那么专业

      

      于是我就想:如何实现这样的效果呢:数据库中只存储英文名称:如University,别人一看就知道大学,但前台上,我要显示的是“大学”两个汉字,如下:

      

      于是我就编写了一个枚举的通用类:

      

    枚举操作类
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;
    using System.Data;
    using System.Windows.Forms;

    namespace WindowsFormsApplication1
    {
    public class EnumUtils<Tenum>
    {
    public static DataTable GetAllEnums()
    {
    Type t
    = typeof(Tenum);
    FieldInfo[] fieldInfoList
    = t.GetFields();
    DataTable dt
    = new DataTable();
    dt.Columns.Add(
    "Text", typeof(string));
    dt.Columns.Add(
    "Value", typeof(string));
    foreach (FieldInfo tField in fieldInfoList)
    {
    if (!tField.IsSpecialName)
    {
    DataRow dr
    = dt.NewRow();
    dr[
    "Value"] = tField.Name;
    EnumDescriptionAttribute[] enumAttributelist
    = (EnumDescriptionAttribute[])tField.GetCustomAttributes(typeof(EnumDescriptionAttribute), false);
    if (enumAttributelist != null && enumAttributelist.Length > 0)
    {
    dr[
    "Text"] = enumAttributelist[0].Description;
    }
    else
    {
    dr[
    "Text"] = tField.Name;
    }
    dt.Rows.Add(dr);
    }
    }
    return dt;
    }
    public static string GetText(Tenum enumInstance)
    {
    Type t
    = typeof(Tenum);
    FieldInfo[] fieldInfoList
    = t.GetFields();
    string strReturn = string.Empty;
    foreach (FieldInfo tField in fieldInfoList)
    {
    if (!tField.IsSpecialName && tField.Name.ToLower() == enumInstance.ToString().ToLower())
    {
    EnumDescriptionAttribute[] enumAttributelist
    = (EnumDescriptionAttribute[])tField.GetCustomAttributes(typeof(EnumDescriptionAttribute), false);
    if (enumAttributelist != null && enumAttributelist.Length > 0)
    {
    strReturn
    = enumAttributelist[0].Description;
    break;
    }
    }
    }
    return strReturn;
    }
    public static string GetValue(Tenum enumInstance)
    {
    Type t
    = typeof(Tenum);
    FieldInfo[] fieldInfoList
    = t.GetFields();
    string strReturn = string.Empty;
    foreach (FieldInfo tField in fieldInfoList)
    {
    if (!tField.IsSpecialName && tField.Name.ToLower() == enumInstance.ToString().ToLower())
    {
    strReturn
    = tField.Name;
    break;
    }
    }
    return strReturn;
    }
    public static Tenum GetEnum(string Value)
    {
    Type t
    = typeof(Tenum);
    FieldInfo field
    = t.GetField(Value);
    return (Tenum)System.Enum.Parse(t, Value);
    }
    public static void BindListControl(ListControl listControl)
    {
    listControl.DisplayMember
    = "Text";
    listControl.ValueMember
    = "Value";
    listControl.DataSource
    = GetAllEnums();
    }
    }
    [AttributeUsage(AttributeTargets.Enum
    | AttributeTargets.Field, AllowMultiple = false)]
    public class EnumDescriptionAttribute : Attribute
    {
    private string description;
    public string Description
    {
    get
    {
    return this.description;
    }
    }
    public EnumDescriptionAttribute(string description)
    :
    base()
    {
    this.description = description;
    }
    }

    }

     枚举申明时如下:

    代码
    public enum EStueType
    {
    [EnumDescription(
    "小学")]
    Primaryschool,
    [EnumDescription(
    "初中")]
    JuniorHighSchool,
    [EnumDescription(
    "大学")]
    HighSchool,
    [EnumDescription(
    "大学")]
    University
    }

     前台绑定时:EnumUtils<EStueType>.BindListControl(this.comboBox1); 

    获得绑定值时(枚举类型): EnumUtils<EStueType>.GetEnum(this.comboBox1.SelectedValue.ToString());;

    获得显示值时(枚举显示名称):EnumUtils<EStueType>.GetText(EStueType.HighSchool);

    示例效果如下:

    OK,一切问题解决

    示例下载地址:https://files.cnblogs.com/Deper/%e6%9e%9a%e4%b8%be%e6%93%8d%e4%bd%9c%e7%b1%bb%e7%a4%ba%e4%be%8b.rar

  • 相关阅读:
    LeetCode 83. Remove Duplicates from Sorted List (从有序链表中去除重复项)
    LeetCode 21. Merge Two Sorted Lists (合并两个有序链表)
    LeetCode 720. Longest Word in Dictionary (字典里最长的单词)
    LeetCode 690. Employee Importance (职员的重要值)
    LeetCode 645. Set Mismatch (集合不匹配)
    LeetCode 500. Keyboard Row (键盘行)
    LeetCode 463. Island Perimeter (岛的周长)
    115.Distinct Subsequences
    55.Jump Game
    124.Binary Tree Maximum Path Sum
  • 原文地址:https://www.cnblogs.com/Deper/p/1781087.html
Copyright © 2011-2022 走看看