如何使用C#枚举(Enum)优化时间设置校验逻辑?
优化日期差值校验代码实现
需求:根据数据库返回的「1 HOUR」「2 HOURS」「1 WEEK」等时间设置,计算两个日期的差值并校验是否匹配该设置。当前通过多个IF判断实现,希望精简优化代码。数据库返回的设置与Enum的Description一致,每次仅返回单个值,「ALWAYS」设置直接返回true。
原实现代码
public enum TaskSchedulingEnum : int { [Description("1 HOUR")] OneHour = 1, [Description("2 HOURS")] TwoHours = 2, [Description("8 HOURS")] EightHours = 8, [Description("1 DAY")] OneDay = 1, [Description("3 DAYS")] ThreeDays = 3, [Description("1 WEEK")] OneWeek = 1, [Description("2 WEEKS")] TwoWeeks = 2, [Description("1 MONTH")] OneMonth = 1, [Description("ALWAYS")] Always = 14 } private async Task<bool> GetUserSettings(string companyId, DateTime? TaskStartDateTime) { // get company settings ... var settings = await projulSettingsService.GetCompanyNotificationSettings(companyId, ProjulSettingsTypeEnum.Notifications); var scheduleSettings = string.Empty; if (settings.Where(x => x.Name == ProjulPortalSettings.GeneralSettingsNotificationIsDisabled).Select(x => x.Value).FirstOrDefault() == "false") { scheduleSettings = JsonConvert.DeserializeObject<string>(settings.Where(x => x.Name == ProjulPortalSettings.NotificationTaskAssignedImmediateWindow).Select(x => x.Value).FirstOrDefault()); if (!string.IsNullOrEmpty(scheduleSettings)) { var _timespan = (DateTime.UtcNow - TaskStartDateTime).Value; var difference = _timespan.TotalHours; // in hours.. TimeSpan days = TimeSpan.FromHours(difference); // days.. var weeks = (days.TotalDays % 365) / 7; // weeks var months = (days.TotalDays % 365) / 30; // months var list = ApplicationExtensions.GetEnumList<TaskSchedulingEnum>().ToList(); var _val = list.Where(x => x.Text == scheduleSettings).FirstOrDefault(); if (scheduleSettings == TaskSchedulingEnum.OneHour.GetEnumDescrip() || scheduleSettings == TaskSchedulingEnum.TwoHours.GetEnumDescrip() || scheduleSettings == TaskSchedulingEnum.EightHours.GetEnumDescrip()) { if (difference == Convert.ToDouble(_val.Value)) return true; } else if (scheduleSettings == TaskSchedulingEnum.OneDay.GetEnumDescrip() || scheduleSettings == TaskSchedulingEnum.ThreeDays.GetEnumDescrip()) { if (days.TotalDays == Convert.ToDouble(_val.Value)) return true; } else if (scheduleSettings == TaskSchedulingEnum.OneWeek.GetEnumDescrip() || scheduleSettings == TaskSchedulingEnum.TwoWeeks.GetEnumDescrip()) { if (weeks == Convert.ToDouble(_val.Value)) return true; } else if (scheduleSettings == TaskSchedulingEnum.OneMonth.GetEnumDescrip()) { if (months == Convert.ToDouble(_val.Value)) return true; } else if (scheduleSettings == TaskSchedulingEnum.Always.GetEnumDescrip()) { return true; } return false; } } return false; }
优化后的实现代码
// 枚举扩展方法:根据Description获取对应的枚举值 public static class EnumExtensions { public static TaskSchedulingEnum GetTaskSchedulingEnumFromDescription(string description) { foreach (var field in typeof(TaskSchedulingEnum).GetFields()) { if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attr && attr.Description == description) { return (TaskSchedulingEnum)field.GetValue(null); } } throw new ArgumentException($"无效的时间设置:{description}"); } // 复用原有的GetEnumDescrip方法(如果已存在),这里补充实现示例 public static string GetEnumDescrip(this TaskSchedulingEnum @enum) { var field = typeof(TaskSchedulingEnum).GetField(@enum.ToString()); if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attr) { return attr.Description; } return @enum.ToString(); } } public enum TaskSchedulingEnum : int { [Description("1 HOUR")] OneHour = 1, [Description("2 HOURS")] TwoHours = 2, [Description("8 HOURS")] EightHours = 8, [Description("1 DAY")] OneDay = 1, [Description("3 DAYS")] ThreeDays = 3, [Description("1 WEEK")] OneWeek = 1, [Description("2 WEEKS")] TwoWeeks = 2, [Description("1 MONTH")] OneMonth = 1, [Description("ALWAYS")] Always = 14 } private async Task<bool> GetUserSettings(string companyId, DateTime? taskStartDateTime) { // 边界判断:任务开始时间为空直接返回false if (!taskStartDateTime.HasValue) return false; var settings = await projulSettingsService.GetCompanyNotificationSettings(companyId, ProjulSettingsTypeEnum.Notifications); // 通知禁用则返回false var isDisabled = settings.FirstOrDefault(x => x.Name == ProjulPortalSettings.GeneralSettingsNotificationIsDisabled)?.Value == "true"; if (isDisabled) return false; // 获取并解析时间设置 var scheduleSettingJson = settings.FirstOrDefault(x => x.Name == ProjulPortalSettings.NotificationTaskAssignedImmediateWindow)?.Value; if (string.IsNullOrEmpty(scheduleSettingJson)) return false; var scheduleSettings = JsonConvert.DeserializeObject<string>(scheduleSettingJson); if (string.IsNullOrEmpty(scheduleSettings)) return false; // ALWAYS设置直接返回true if (scheduleSettings == TaskSchedulingEnum.Always.GetEnumDescrip()) return true; // 转换为枚举值 var scheduleEnum = EnumExtensions.GetTaskSchedulingEnumFromDescription(scheduleSettings); var timeDiff = DateTime.UtcNow - taskStartDateTime.Value; // 用字典映射枚举到校验逻辑,消除冗余IF var validationRules = new Dictionary<TaskSchedulingEnum, Func<TimeSpan, bool>> { { TaskSchedulingEnum.OneHour, ts => ts.TotalHours == 1 }, { TaskSchedulingEnum.TwoHours, ts => ts.TotalHours == 2 }, { TaskSchedulingEnum.EightHours, ts => ts.TotalHours == 8 }, { TaskSchedulingEnum.OneDay, ts => ts.TotalDays == 1 }, { TaskSchedulingEnum.ThreeDays, ts => ts.TotalDays == 3 }, { TaskSchedulingEnum.OneWeek, ts => ts.TotalDays / 7 == 1 }, { TaskSchedulingEnum.TwoWeeks, ts => ts.TotalDays / 7 == 2 }, { TaskSchedulingEnum.OneMonth, ts => ts.TotalDays / 30 == 1 } }; return validationRules.TryGetValue(scheduleEnum, out var validator) ? validator(timeDiff) : false; }
优化核心要点
- 消除冗余IF判断:用字典映射枚举值到对应的差值校验逻辑,新增时间设置只需在字典中添加条目,维护成本更低。
- 简化枚举转换:通过扩展方法直接根据Description获取枚举值,避免遍历列表查找,代码更高效。
- 提前边界判断:对空值、通知禁用、配置为空等情况提前返回,减少嵌套层级,提升代码可读性。
- 移除冗余计算:原代码中多余的中间变量(如
weeks、months)直接整合到校验逻辑中,避免不必要的计算。 - 规范命名:调整变量名符合C#命名规范,提升代码可读性。
内容的提问来源于stack exchange,提问作者Muhammad Kamran
相关产品推荐
相关产品推荐

