c# 扩展方法奇思妙用基础:IsBetween 通用扩展
2015-06-15 19:43
501 查看
相信大家在看了本文的题目之后,马上就能写出 IsBetween 扩展来:
大家的写法可能不尽相同,但效果都是一样的,以上可能是最精简的写法了吧,类似可以写出其它数据类型 IsBetween 来:
不过这样写下去可是很罗嗦的,.net 中的数值类型太多了,除了上面几个还有:
此外,我们还有其它要类型如:string、DateTime 等也要进行 IsBetween 判断,一个一个写来不优雅。
泛型版本 IsBetween 扩展
.Net 中
这个是相当通用的,支持 .net 中的所有数值类型,也支持 string、DateTime,因为它们都实现了 IComparable 接口,下面是一些调用代码:
带
上面的扩展很通用,但还不够好,比如下面的 Person 类:
没有实现任何
使用 .Net 中另外一个关于通用比较的接口
这个扩展需要一个
人员生日 IsBetween 示例代码如下:
类似,我们还可以对人员进行身高、体重、人品等其它方面的 IsBetween 判断,只需要传入不同的 comparer。
针对
之前一篇文章中,我曾说过要针对接口扩展,我们何不针对
这个扩展的应用场景可能不多,这里举一个方便大家理解,假定我们自定义了一个大整数类形:
因为它实
( .Net 中已经有了大整数类型,请参见:BigInteger 结构,不过没有实现
其它比较扩展
有了上面的 IsBetween 扩展,再写其它比较扩展就易如反掌了,比如下面几个:
public static bool IntIsBetween(this int i, int lowerBound, int upperBound, bool includeLowerBound = false, bool includeUpperBound = false) { return (includeLowerBound && i == lowerBound) || (includeUpperBound && i == upperBound) || (i > lowerBound && i < upperBound); }
大家的写法可能不尽相同,但效果都是一样的,以上可能是最精简的写法了吧,类似可以写出其它数据类型 IsBetween 来:
public static bool IntIsBetween(this long i, long lowerBound, long upperBound, bool includeLowerBound = false, bool includeUpperBound = false) { return (includeLowerBound && i == lowerBound) || (includeUpperBound && i == upperBound) || (i > lowerBound && i < upperBound); } public static bool DoubleIsBetween(this float i, float lowerBound, float upperBound, bool includeLowerBound = false, bool includeUpperBound = false) { return (includeLowerBound && i == lowerBound) || (includeUpperBound && i == upperBound) || (i > lowerBound && i < upperBound); }
不过这样写下去可是很罗嗦的,.net 中的数值类型太多了,除了上面几个还有:
short、long、ushort、uint、ulong、double、decimal…
此外,我们还有其它要类型如:string、DateTime 等也要进行 IsBetween 判断,一个一个写来不优雅。
泛型版本 IsBetween 扩展
.Net 中
IComparable<T>接口 定义了值类型或类的通用比较方法,借助于此接口,写一个通用的 IsBetween 就容易多了:
public static bool IsBetween<T>(this T t, T lowerBound, T upperBound, bool includeLowerBound = false, bool includeUpperBound = false) where T: IComparable<T> { if(t == null) throw new ArgumentNullException("t"); var lowerCompareResult = t.CompareTo(lowerBound); var upperCompareResult = t.CompareTo(upperBound); return (includeLowerBound && lowerCompareResult == 0) || (includeUpperBound && upperCompareResult == 0) || (lowerCompareResult > 0 && upperCompareResult < 0); }
这个是相当通用的,支持 .net 中的所有数值类型,也支持 string、DateTime,因为它们都实现了 IComparable 接口,下面是一些调用代码:
//int bool b0 = 3.IsBetween(1, 5); bool b1 = 3.IsBetween(1, 3, includeUpperBound: true); bool b2 = 3.IsBetween(3, 5, includeLowerBound: true); //double bool b3 = 3.14.IsBetween(3.0, 4.0); //string bool b4 = "ND".IsBetween("NA", "NC"); //DateTime bool b5 = new DateTime(2011, 2, 17).IsBetween(new DateTime(2011, 1, 1), new DateTime(2011, 3, 1));
带
IComparer<T>参数的 IsBetween 扩展
上面的扩展很通用,但还不够好,比如下面的 Person 类:
public class Person { public string Name { get; set; } public DateTime Birthday { get; set; } }
没有实现任何
IComparable<T>接口,但我们需要确定某人是否界于另外两人这间,根据生日或其它条件判断。
使用 .Net 中另外一个关于通用比较的接口
IComparer<T>接口,我们再创建一个扩展:
public static bool IsBetween<T>(this T t, T lowerBound, T upperBound, IComparer<T> comparer, bool includeLowerBound = false, bool includeUpperBound = false) { if (comparer == null) throw new ArgumentNullException("comparer"); var lowerCompareResult = comparer.Compare(t, lowerBound); var upperCompareResult = comparer.Compare(t, upperBound); return (includeLowerBound && lowerCompareResult == 0) || (includeUpperBound && upperCompareResult == 0) || (lowerCompareResult > 0 && upperCompareResult < 0); }
这个扩展需要一个
IComparer<T>的实例,我们先来实现人员生日的“比较器” :
public class PersonBirthdayComparer : IComparer<Person> { public int Compare(Person x, Person y) { return Comparer<DateTime>.Default.Compare(x.Birthday, y.Birthday); } }
人员生日 IsBetween 示例代码如下:
var p1= new Person{ Name = "鹤冲天", Birthday = new DateTime(1990, 1, 1)}; var p2= new Person{ Name = "鹤中天", Birthday = new DateTime(2000, 1, 1)}; var p3= new Person{ Name = "鹤微天", Birthday = new DateTime(2010, 1, 1)}; bool b6 = p2.IsBetween(p1, p3, new PersonBirthdayComparer());
类似,我们还可以对人员进行身高、体重、人品等其它方面的 IsBetween 判断,只需要传入不同的 comparer。
针对
IComparable<T>接口的 IsBetween 扩展
之前一篇文章中,我曾说过要针对接口扩展,我们何不针对
IComparable<T>接口 进行扩展呢:
public static bool IsBetween<T>(this IComparable<T> t, T lowerBound, T upperBound, bool includeLowerBound = false, bool includeUpperBound = false) { if (t == null) throw new ArgumentNullException("t"); var lowerCompareResult = t.CompareTo(lowerBound); var upperCompareResult = t.CompareTo(upperBound); return (includeLowerBound && lowerCompareResult == 0) || (includeUpperBound && upperCompareResult == 0) || (lowerCompareResult > 0 && upperCompareResult < 0); }
这个扩展的应用场景可能不多,这里举一个方便大家理解,假定我们自定义了一个大整数类形:
public class BigInt: IComparable<int>, IComparable<double> { //... public int CompareTo(int other) { //... } public int CompareTo(double other) { //... } }
因为它实
IComparable<int>和
IComparable<double>,所以可以和 int 和 double 进行比较,则可以如下使用:
BigInt bi = new BigInt(); bool b8 = bi.IsBetween(10, 20); bool b9 = bi.IsBetween(1.424E+12, 2.3675E+36);
( .Net 中已经有了大整数类型,请参见:BigInteger 结构,不过没有实现
IComparable<int>和
IComparable<double>)
其它比较扩展
有了上面的 IsBetween 扩展,再写其它比较扩展就易如反掌了,比如下面几个:
LessThan LessOrEquals GreatOrEquals GreatThan
相关文章推荐
- c# 扩展方法奇思妙用基础:string 常用扩展
- c# 扩展方法奇思妙用基础:WhereIf 扩展
- 关于C#控制台输出中文字符乱码解决方案
- C#事件机制
- C#中一道关于线程同步的练习题——模拟多窗口售票
- WinForm(C#)中MDI子窗体最大化的问题
- C#基础及记忆概念
- C#操作XML(三)
- C# 打印多页tif
- C# 后台服务 web.config 中 项“ConnectionString”已添加。问题
- C#模拟POST登录cnblogs并发布文章
- C#--Web数据分页
- C# Socket SSL通讯笔记
- c#通过属性的名字获取值
- 压缩文本、字节或者文件的压缩辅助类-GZipHelper 欢迎收藏
- C#对图片的操作
- c#FileStream文件读写(转)
- C#(WPF)为Grid添加实线边框
- C# Thread STA模式 与MTA模式
- C#线程池