热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#学习教程:C#:Enum反模式分享

C#:Enum反模式有人一直在谈论Enums一般违反清洁代码原则,所以我正在寻找人们最喜欢的Enum反模式和替代解决方案。例如,我见过这样的代码:switch(enumValue)

C#:Enum反模式

有人一直在谈论Enums一般违反清洁代码原则,所以我正在寻找人们最喜欢的Enum反模式和替代解决方案。

例如,我见过这样的代码:

switch(enumValue) { case myEnum.Value1: // ... break; case myEnum.Value2: // ... break; } 

它比带有魔术字符串的switch语句更好一步,但这可能已经通过工厂,容器或其他模式更好地解决了。

甚至像这样的老派代码:

 if(enumValue == myEnum.Value1) { // ... } else if (enumValue == myEnum.Value2) { // ... } 

您对枚举有哪些其他反模式和更好的实现

我认为Enums非常有用。 我为Enum写了一些扩展,为它的使用增加了更多的价值

首先,有Description扩展方法

 public static class EnumExtensions { public static string Description(this Enum value) { var entries = value.ToString().Split(ENUM_SEPERATOR_CHARACTER); var description = new string[entries.Length]; for (var i = 0; i  0) ? attributes[0].Description : entries[i].Trim(); } return String.Join(", ", description); } private const char ENUM_SEPERATOR_CHARACTER = ','; } 

这将允许我像这样定义en enum:

  public enum MeasurementUnitType { [Description("px")] Pixels = 0, [Description("em")] Em = 1, [Description("%")] Percent = 2, [Description("pt")] Points = 3 } 

并通过执行以下操作获取标签: var myLabel = rectangle.widthunit.Description() (不需要switch语句)。

如果rectangle.widthunit = MeasurementUnitType.Pixels ,它将返回“px”,如果rectangle.widthunit = MeasurementUnitType.Pixels ,它将返回“px,em” rectangle.widthunit = MeasurementUnitType.Pixels | MeasurementUnitType.Em

然后,有一个

  public static IEnumerable GetIntBasedEnumMembers(Type @enum) { foreach (FieldInfo fi in @enum.GetFields(BindingFlags.Public | BindingFlags.Static)) yield return (int)fi.GetRawConstantValue(); } 

这将让我遍历任何基于int的值的枚举并返回int值本身。

我发现这些在一个已经很有用的概念中非常有用。

我看到有两个 switch语句作为非OO设计的症状, 如本答案中进一步解释的那样 。

这不是答案,而是对Enum反模式列表的贡献。

在今天早上的代码审查期间,我遇到了类似于以下的案例,所有案例都在同一个class级。

两种情况:

  1. 喝酒前
  2. 喝完后

..

  public enum ListEnum { CategoryOne, CategoryTwo, CategoryThree, CategoryFour } public class UIELementType { public const string FactoryDomain = "FactoryDomain"; public const string Attributes = "Attributes"; } 

使用不反模式的枚举。 在一些关于重构的书中,这段代码用于演示如何用多态替换它。 当你在代码中过度使用枚举时就可以了。

这完全取决于你尝试用枚举做什么。

  1. 如果您试图阻止开发人员将魔术数字传递到您的操作中,并且您希望保持数据引用完整性与您的数据库完整,那么,是的! 使用T4-Templates(使用您的ORM)转到您的MeasurementUnitTypes表并生成一个枚举,其ID,Name和Description列与枚举’int,Enum_Name和Description属性相匹配(其他字段数据的好方法可以枚举@danijels)如上所述。 如果向MeasurementUnitTypes表中添加新的Measurement Type,则可以右键单击并运行T4-Template,并为表中添加的新行生成枚举代码。 我不喜欢我的应用程序中没有链接到我的数据库的硬编码数据,因此提到了T4模板方法。 它是不可扩展的,否则……如果某个其他外部系统想要检索我们系统中使用的测量标准,那么它在系统中是硬编码的,您不能通过服务将其暴露给客户端。 那就离开了。

  2. 如果目的不是数据相关的,并且你有一些逻辑分配给特定的枚举,那么NO! 这违反了SOLID(开放式关闭原则),就像你在应用程序的某个地方应用一个开关或一堆Ifs来操作每个枚举的逻辑一样,如果你这样做真的很糟糕这些开关或者Ifs都在整个节目……祝你好运添加一个新的枚举……所以它不是为了扩展而打开,而是因为你需要修改现有代码而根据SOLID原则关闭修改。

    如果您的选择是2,那么我建议您使用@danijels评论中的示例用以下内容替换您的枚举:

     public interface IMeasurementUnitType { int ID { get; } string Description { get; } // Just added to simulate a action needed in the system string GetPrintMessage(int size); } 

上面的代码定义了每个度量应遵循的接口(代码契约)。 现在让我们定义百分比和像素测量:

  public class PixelsMeasurementUnitType : IMeasurementUnitType { public int ID => 1; public string Description => "Pixel"; public string GetPrintMessage(int size) { return $"This is a {Description} Measurement that is equal to {size} pixels of the total screen size"; } } public class PercentMeasurementUnitType : IMeasurementUnitType { public int ID => 2; public string Description => "Persentage"; public string GetPrintMessage(int size) { return $"This is a {Description} Measurement that is equal to {size} persent of total screen size (100)"; } } 

所以我们定义了两种类型,我们将在代码中使用它们,如下所示:

  var listOfMeasurmentTypes = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(s => s.GetTypes()) .Where(p => typeof(IMeasurementUnitType).IsAssignableFrom(p) && !p.IsInterface) .ToList(); 

这里我们获取扩展IMeasurementUnitType接口的所有TYPES而不是接口本身。 现在我们可以使用Activator创建类的实例来填充我们的UI控件:

  public IEnumerable GetInstantiatedClassesFromTypes(List types) { foreach (var type in types) { yield return (IMeasurementUnitType)Activator.CreateInstance(type); } } 

您可以将上面的代码更改为任何类型的通用代码,现在生活发生,客户端提供一个名为Point的新测量单位类型作为新要求,我不需要更改任何代码,只需添加新类型(扩展)代码不修改)。 新类型将在应用程序中自动获取。

  public class PointMeasurementUnitType : IMeasurementUnitType { public int ID => 3; public string Description => "Point"; public string GetPrintMessage(int size) { return $"This is a {Description} Measurement that is equal to {size} points of total screen size"; } } 

一个好主意是在启动应用程序时尝试缓存类型以获得性能优势,或者尝试使用您选择的DI容器。

此外,有人可以争辩说,在你的应用程序的某个地方,你需要区分类型,我同意,但是你想要苹果与苹果。 因此,尽可能尝试应用与此类型相同的原则。 如果在某种类型的图形处理器(例如)类中使用此类型,则具有IGraphicsProcessor并具有区分这些类型的具体类,例如PersentageAndPixelGraphicsProcessor(从IGraphicsProcessor扩展),或者如果它仅区分一种类型,则称为PersentageGraphicsProcessor。

很抱歉HUGE SA,但我真的很喜欢enum,但是当我尝试使用枚举分离逻辑时,我觉得它是一个强大的反模式。

欢迎评论,

上述就是C#学习教程:C#:Enum反模式分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—编程笔记


推荐阅读
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 开发笔记:select from具体执行相关知识介绍及案例分析
    本文由编程笔记小编整理,主要介绍了select from具体执行相关的知识,包括数据插入、查询最小rowID、查询每个重复名字的最小rowID、删除重复数据等操作,并提供了案例分析。希望对读者有一定的参考价值。 ... [详细]
author-avatar
圊渘湜壞亾
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有