博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对泛型类型进行判等(比较)
阅读量:5133 次
发布时间:2019-06-13

本文共 1811 字,大约阅读时间需要 6 分钟。

这个问题似乎已经讨论过很多次了,就当是给自己做笔记,我再总结一次。

问题背景是我在给IEnumerable<T>添加一个扩展方法时,要判断两个元素是否相等,假设分别是left和right,类型为T,T没有任何约束。首先自然而然地写出了这样的代码:

if
 (left 
==
 right) // <-- Compile error
{
dot.gif
}

更自然地,我得到了一个编译错误,因为类型T上根本没有定义"=="运算符。

后来在网上看到,很多人在这个时候会采用添加约束"where T: IComparable<T>"的方法(称为方案1)。这是一个解决方案,但明显太cuo了。首先,大多数类都不实现IComparable<T>接口;其次,那些实现了IComparable接口的怎么办?而且实际上我根本不需要比较大小,只是比较是否相等,更进一步,我只需要判断对象是否是同一个,即是否是ReferenceEquals的。由此我们可以想到,object类实现了一个静态Equals (obj, obj)方法,对于引用类型,它相当于ReferenceEquals方法,对于值类型,它会进行按位比较。这就是所谓“默认的比较方式”。于是最终代码如下:

if
 (
object
.Equals (left, right)) // Solution 2.
{
dot.gif
}
这是方案2.

但在当时我没想到那么多,我用了一个比较ws的方式,我把比较操作外包出去了:

 

public
 IEnumerable
<
T
>
 DemoMethod<T> (
this
 IEnumerable
<
T
>
 source,
                      Func
<
T, T, 
bool
>
 equalityComparison)
{
dot.gif
    
if
 (equalityComparison (left, right))
    {
    dot.gif
    }
dot.gif
}

然后在调用方:

foreach
 (var item 
in
 
"
abc
"
.DemoMethod ((x, y) 
=>
 x 
==
 y)) 
//
string实现IEnumerable<char>接口,而char支持"=="操作符
{
dot.gif
}

这是方案3.

此外,参考List<T>.Sort()方法的实现,可以知道有个Comparer<T>.Default的默认比较器,其上有个Compare方法,于是得到方案4:

if
 (Comparer
<
T
>
.Default.Compare (left, right) 
==
 
0
)
{
dot.gif
}
然而当无法取得所比较类型的默认比较器时,在Compare方法上会引发ArgumentException异常。

三种方案比较,显然方案1需要添加约束,太不灵活;方案2可以应付大多数常规情况,编码比较方便,但如果需要比较大小则无法实现,这时可以考虑方案4,但由于实现了默认比较器的类型实在很少,方案4也是个鸡肋;方案3则最灵活,可以由方法用户自行指定比较方案。可谓2、3皆有所长,可以作为重载都写上。事实上,方案2可以实现为对方案3的调用:

public
 IEnumerable
<
T
>
 DemoMethod<T> (
this
 IEnumerable
<
T
>
 source)
{
    source.DemoMethod (
object
.Equals);
}

 

那能不能再进一步,在C#4.0中可选参数的支持下,不用重载,只写一个方法就行了呢?

public
 IEnumerable
<
T
>
 DemoMethod
<
T
>
 (
this
 IEnumerable
<
T
>
 source,
                      Func
<
T, T, 
bool
>
 equalityComparison = object.Equals)
// Compile error: Default parameter value for 'equalityComparison' must be a compile-time constant

实验结果是不行,因为可选参数的默认值必须是编译时常量,而一个方法的引用(其实应该是函数地址吧)在编译时是无法确定的。

转载于:https://www.cnblogs.com/Gildor/archive/2009/09/05/1560671.html

你可能感兴趣的文章
poj2569
查看>>
使用pygal_maps_world.i18n中数据画各大洲地图
查看>>
sql server必知多种日期函数时间格式转换
查看>>
jQuery EasyUI 的下拉选择combobox后台动态赋值
查看>>
timeline时间轴进度“群英荟萃”
查看>>
python if else elif statement
查看>>
网络编程
查看>>
文本隐藏(图片代替文字)
查看>>
java面试题
查看>>
提高码力专题(未完待续)
查看>>
pair的例子
查看>>
前端框架性能对比
查看>>
uva 387 A Puzzling Problem (回溯)
查看>>
12.2日常
查看>>
同步代码时忽略maven项目 target目录
查看>>
Oracle中包的创建
查看>>
团队开发之个人博客八(4月27)
查看>>
发布功能完成
查看>>
【原】小程序常见问题整理
查看>>
C# ITextSharp pdf 自动打印
查看>>