前言:国内码农与国外优秀程序员的最大区别是,我们的专家、教授喜欢唾沫横飞地,夸夸其谈语言特性、框架、性能,唯一目的是带私货(书籍或教程),很少能写出真有用的程序。差距在哪呢?基础!基础!基础!
1 优缺点共存是所有语言、语法的常态
枚举enum是常用的数据类型,有很多优点。
枚举使用过程也有很多不便,比如:值、名字、描述的对应关系不便检索。
2 高级一点的使用方法
下面的代码具有较高的参考价值,建议仔细阅读。
using System;
using System.IO;
using System.Text;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
/// <summary>
/// 便于使用的枚举
/// </summary>
namespace K50018.Kernal
{
/// <summary>
/// 一个枚举实例
/// </summary>
public static class EnumHelper
{
public enum EnumExample
{
[Description("号球")]
CODE = 0,
[Description("数字")]
DIGITAL,
[Description("红球")]
RED_BALL,
[Description("蓝球")]
BLUE_BALL,
[Description("前区")]
FIRST_BALL,
[Description("后区")]
SECOND_BALL,
}
/// <summary>
/// 按枚举变量提取枚举的描述(标题)
/// </summary>
/// <param name="cs">枚举值,比如:EnumExample.CODE</param>
/// <returns></returns>
public static string GetDescription(EnumExample cs)
{
return GetEnumDescription(cs);
}
/// <summary>
/// 按序号提取枚举的描述(标题)
/// </summary>
/// <param name="index">0开始的序号</param>
/// <returns></returns>
public static string GetDescription(int index)
{
Array array = Enum.GetValues(typeof(EnumExample));
if (index < 0 || index >= array.Length) return "";
EnumExample cs = (EnumExample)array.GetValue(index);
return GetDescription(cs);
}
/// <summary>
/// 按枚举名字提取的描述(标题)
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static string GetDescription(string name)
{
string[] array = Enum.GetNames(typeof(EnumExample));
for (int i = 0; i < array.Length; i++)
{
if (array[i].ToUpper() == name.ToUpper())
{
return GetDescription(index: i);
}
}
return "";
}
/// <summary>
/// 提取标题的基础函数
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static string GetEnumDescription(Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
return (attributes.Length > 0) ? attributes[0].Description : value.ToString();
}
/// <summary>
/// 将枚举转为三元组列表
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static List<Tuple<int, string, string>> ToList<T>()
{
List<Tuple<int, string, string>> r = new List<Tuple<int, string, string>>();
Array xa = Enum.GetValues(typeof(T));
string[] na = Enum.GetNames(typeof(T));
for (int i = 0; i < na.Length; i++)
{
EnumExample cs = (EnumExample)xa.GetValue(i);
r.Add(new Tuple<int, string, string>((int)cs, na[i], GetDescription(i)));
}
return r;
}
/// <summary>
/// 另外一种按序号提取枚举描述的方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="index"></param>
/// <returns></returns>
public static string GetDescription<T>(int index)
{
List<Tuple<int, string, string>> r = ToList<T>();
return r[index].Item3;
}
/// <summary>
/// 应用实例
/// </summary>
/// <returns></returns>
public static string Drive()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("1 按枚举变量提取描述");
sb.AppendLine("EnumExample.CODE -> " + GetDescription(EnumExample.CODE));
sb.AppendLine("2 按序号量提取描述");
sb.AppendLine("EnumExample[3] -> " + GetDescription(3));
sb.AppendLine("3 按枚举名提取描述(大小写无关)");
sb.AppendLine("EnumExample[\"code\"] -> " + GetDescription("code"));
sb.AppendLine("4 转换为三元组");
int idx = 0;
foreach (Tuple<int, string, string> tx in ToList<EnumExample>())
{
sb.Append(idx + ": ");
sb.Append("value=" + tx.Item1.ToString() + " ");
sb.Append("name=" + tx.Item2.ToString() + " ");
sb.AppendLine("description=" + tx.Item3.ToString() + " ");
idx++;
}
sb.AppendLine("5 按三元组的序号提取描述");
sb.AppendLine("Tuple[3] -> " + GetDescription<EnumExample>(3));
return sb.ToString();
}
}
}
运行结果:
可以把 枚举enum 当作 类class 来使用就方便多了。
3 未来
.NET 8 之后。
国家把大量的资金投入高校与研究所,等于肉包子打狗,
别指望他们能写出任何一个有用的软件。
如果你的枚举类型只是用来表示一些简单的常量,而且不需要进行复杂的操作或逻辑,那么你可以使用枚举,它更简单,更直观,更高效。但是,如果你的枚举类型需要包含一些额外的信息,或者需要提供一些特定的方法,或者需要实现一些接口,或者需要继承一些类,那么你可以使用枚举类 Enumeration ,它更灵活,更易于维护。
Enumeration类是一个抽象类,它实现了IComparable接口,有两个属性:Name和Id,分别表示枚举的名称和值。它的构造函数接受两个参数,用于初始化这两个属性。它重写了ToString方法,返回Name属性的值。它还重写了Equals和GetHashCode方法,用于判断两个枚举对象是否相等,以及计算枚举对象的哈希值。它还提供了以下几个静态方法:
GetAll<T>:返回一个包含所有枚举对象的数组,其中T是Enumeration的子类。
AbsoluteDifference(Enumeration firstValue, Enumeration secondValue):返回两个枚举对象的Id属性的绝对差值。
FromValue<T>(int value):根据value参数查找对应的枚举对象,如果不存在则抛出异常。
FromDisplayName<T>(string displayName):根据displayName参数查找对应的枚举对象,如果不存在则抛出异常。
Parse<T, K>(K value, string deion, Func<T, bool> predicate):根据value参数和predicate委托查找对应的枚举对象,如果不存在则抛出异常。这是一个私有方法,被FromValue<T>和FromDisplayName<T>方法调用。
Enumeration类的设计非常精巧,它提供了一种通用的方式来创建枚举类型,只需要继承它并定义一些静态字段即可。那么,这样的设计到底有哪些好处呢?其实,通过与枚举进行对比,就可以找到答案,我们来看一看它们的区别:枚举类可以包含更多的信息,而不仅仅是一个整数值。例如,OrderStatus类除了有Id属性外,还有Name属性,用于表示订单状态的名称。这样可以方便地在界面上显示订单状态,而不需要额外的转换逻辑。而枚举只能表示一个整数值,如果要显示名称,就需要使用switch语句或者字典来映射。
枚举类可以提供更多的方法,而不仅仅是一些基本的操作。例如,OrderStatus类提供了List,FromName,From等方法,用于获取所有的订单状态,或者根据名称或值查找订单状态。而枚举只能使用Enum类的一些静态方法,如Enum.GetValues,Enum.GetName,Enum.Parse等,这些方法的参数和返回值都是object类型,需要进行类型转换,而且容易出错。
枚举类可以实现接口,而枚举不能。例如,Enumeration类实现了IComparable接口,表示它可以进行比较。这样可以方便地对枚举对象进行排序,或者使用一些LINQ方法,如Min,Max,OrderBy等。而枚举不能实现接口,只能使用默认的比较规则,即按照整数值的大小比较。
枚举类可以继承其他类,而枚举不能。例如,OrderStatus类继承了Enumeration类,这样可以方便地复用Enumeration类的一些通用的方法和属性,而不需要重复编写代码。而枚举不能继承其他类,只能继承System.Enum类,这是一个密封的类,不能被修改或扩展。