本文是作日志写的,因此没有太多介绍细节。
今天在测试过程中找出了一个问题。
建立日程时,可以选择该日程是每周的周几重复提醒,比如:每周二、四提醒。
因为值的范围只有7天,所以可以使用二进制和与运算来实现多选。
原来的代码是这样写的
public class CalendarModel
{
// some fields
public WeekDayEnum WeekDay { get; set; }
private List<DayOfWeek> dayOfWeeks;
//获取 已选的周几的集合
public List<DayOfWeek> DayOfWeeks
{
get
{
dayOfWeeks = new List<DayOfWeek>();
// Bug, 就是这里 ToString得到的是数值,可能之前他扩展ToString 以取序列
string[] tempWeekDays = WeekDay.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
foreach (string day in tempWeekDays)
{
switch (day.Trim())
{
case "MO":
dayOfWeeks.Add(DayOfWeek.Monday);
break;
case "TU":
dayOfWeeks.Add(DayOfWeek.Tuesday);
break;
case "WE":
dayOfWeeks.Add(DayOfWeek.Wednesday);
break;
case "TH":
dayOfWeeks.Add(DayOfWeek.Thursday);
break;
case "FR":
dayOfWeeks.Add(DayOfWeek.Friday);
break;
case "SA":
dayOfWeeks.Add(DayOfWeek.Saturday);
break;
case "SU":
dayOfWeeks.Add(DayOfWeek.Sunday);
break;
default:
dayOfWeeks.Add(DayOfWeek.Monday);
break;
}
}
return dayOfWeeks;
}
}
// some methods
}
public enum WeekDayEnum
{
None = 0, //无
MO = 1, //周一
TU = 2, //周二....
WE = 4,
TH = 8,
FR = 16,
SA = 32,
SU = 64
}
优化后的代码
public class CalendarModel
{
// some fields
public Weekday Weekday { get; set; }
public List<DayOfWeek> DayOfWeeks
{
get
{
return Weekday.ToOptions().ToDayOfWeeks();
}
}
// not some methods
}
Weekday 不变.
其中ToOptions是 Weekday的扩展方法,在另一个文件中
public static class WeekdayExtensions
{
#region Utilities
/// 转换..(暂未Public)
private static DayOfWeek ToDayOfWeek(this Weekday e)
{
switch (e)
{
case Weekday.MO:
return DayOfWeek.Monday;
case Weekday.TU:
return DayOfWeek.Tuesday;
case Weekday.WE:
return DayOfWeek.Wednesday;
case Weekday.TH:
return DayOfWeek.Thursday;
case Weekday.FR:
return DayOfWeek.Friday;
case Weekday.SA:
return DayOfWeek.Saturday;
case Weekday.SU:
return DayOfWeek.Sunday;
default:
return (DayOfWeek)(-1);
}
}
#endregion
#region Weekday Convert To bit Array
public static int[] ToIntArray(this Weekday[] e)
{
return Array.ConvertAll(e, x => (int)x);
}
#endregion
#region Weekday bit options extensions
/// 是否已选择指定项目
public static bool HasOption(this Weekday e, params Weekday[] param)
{
return BitOptionExtensions.HasOption((int)e, param.ToIntArray());
}
/// 是否已选择指定项目
/// (ToThink,受应用方式影响,暂不开放 int for bit option 的扩展)
//public static bool HasOption(this int e, params Weekday[] param)
//{
// return BitExtensions.HasOption(e, param.ToIntArray());
//}
/// 返回已选择的项
//public static Weekday[] ToOptions(this Weekday e)
public static Weekday[] ToOptions(this Weekday e)
{
var result = from Weekday t in Enum.GetValues(typeof(Weekday)) //or e.AllValues()
where (t & e) == t && (int)t != 0
select t;
return result.ToArray();
}
/// 返回选择后的项目值
public static int ToOptionId(this Weekday[] e)
{
return BitOptionExtensions.ToOptionId(e.ToIntArray());
}
#endregion
/// 我是不太推荐,底层的方法返回List
public static List<DayOfWeek> ToDayOfWeeks(this Weekday[] e)
{
return e.Select(ToDayOfWeek).Where(x=> (int)x != -1).ToList();
}
}
这里的 ToDayOfWeek 方法 是没有改变多少,是可以优化一下
注:在ToPotions中,增加了 (int)t != 0 这是因为 枚举里多了一个 None=0。
(在概念中本没有None)
WeekdayExtensions 内部使用了 BitExtensions
/// <summary>Bit运算选项扩展</summary>
public static class BitOptionExtensions
{
/// 是否已选择指定项
public static bool HasOption(this int e, params int[] param)
{
// 默认 就是 true, 这样会比默认false的时间复杂度小很多。
var result = true;
for (int i = 0; i < param.Length; i++)
{
var temp = param[i];
if (result)
result = temp == (e & temp);
}
return result;
}
/// 返回已选择项集合
/// (即以数组形式分离所有值)
public static int[] ToOptions(this int e, int[] values)
{
var result = from t in values
where (t & e) == t
select t;
return result.ToArray();
}
/// 返回选择后的项目值
public static int ToOptionId(this int[] e)
{
var result = 0;
for (int i = 0; i < e.Length; i++)
{
result = result | e[i];
}
return result;
}
/// 获得所有可选项
public static TEnum[] AllValues<TEnum>(this TEnum e) where TEnum : struct
{
return (from TEnum a in Enum.GetValues(typeof(TEnum)) select a).ToArray();
}
}
上面BitExtensions是可以收留的,WeekdayExtensions是可以复制修改方便以后项目。