比较

一、两类的比较,在介绍之前先来认识封箱和拆箱:

1.封箱(boxing)是把值类型转换为System.Object 类型,或者转换为由值类型实现的接口类型。

拆箱(unboxing)是相反的转换过程。

struct MyStruct

{

public int Val;

}

MyStruct valType1 = new MyStruct();

valType1.Val = 5;

object refType = valType1;

以这种方式封箱变量而创建的对象,包含值类型变量的一个副本的引用,而不包含源值类型变量的引用。

valType1.Val = 6;

MyStruct valType2 = (MyStruct)refType;

Console.WriteLine("valType2.Val = {0}", valType2.Val);

执行这段代码将得到如下输出结果:

valType2.Val = 5

但在把一个引用类型赋予对象时,将执行不同的操作。把MyStruct 改为一个类(不考虑这个类名不合适的情况),即可看到这种情形:

class MyStruct

{

public int Val;

}

如果不修改上面的客户代码,就会得到如下输出结果:

valType2.Val = 6

也可以把值类型封箱到一个接口类型中,只要它们实现这个接口即可。例如,假定MyStruct 类型实现IMyInterface 接口,如下所示:

interface IMyInterface

{

}

struct MyStruct : IMyInterface

{

public int Val;

}

MyStruct valType1 = new MyStruct();

IMyInterface refType = valType1;

//拆箱

MyStruct ValType2 = (MyStruct)refType;

封箱是在没有用户干涉的情况下进行的(即不需要编写任何代码),但拆箱一个值需要进行显式转换,即需要进行数据类型转换(封箱是隐式的,所以不需要进行数据类型转换)。

封箱非常有用,有两个非常重要的原因。首先,它允许在项的类型是object 的集合(如ArrayList)中使用值类型。其次,有一个内部机制允许在值类型上调用object,例如int 和结构。

在比较对象时,常常需要了解它们的类型,才能确定是否可以进行值的比较,之前介绍了GetType()方法,所有的类都从System.Object 中继承了这个方法,这个方法和typeof()运算符一起使用,就可以确定对象的类型(并据此执行操作):

if (myObj.GetType() == typeof(MyComplexClass))

{

// myObj is an instance of the class MyComplexClass.

}

2.本节将介绍比较值的一种简便方式:is 运算符。它可以提供可读性较高的代码,还可以检查基类。

is 运算符并不是说明对象是某种类型的一种方式,而是可以检查对象是否是给定类型,或者是否可以转换为给定类型,如果是,这个运算符就返回true。

is 运算符的语法如下:

<operand> is <type>

这个表达式的结果如下:

如果<type>是一个类类型,而<operand>也是该类型,或者它继承了该类型,或者它可以封箱到该类型中,则结果为true。

如果<type>是一个接口类型,而<operand>也是该类型,或者它是实现该接口的类型,则结果为true。

如果<type>是一个值类型,而<operand>也是该类型,或者它可以拆箱到该类型中,则结果为true。

二、值比较:

进行值比较,可以使用运算符重载。另一个方法是使用IComparable 和IComparer 接口,它们可以用标准的方式定义比较对象的过程。这是由.NET Framework 中各种集合类提供的方式,是对集合中的对象进行排序的一种绝佳方式。

1)运算符重载:

说明:

bool op3 = op1 == op2;

使用==二元运算符来比较两个对象,看看它们是否引用同一个对象,而不是验证它们的值是否相等。

我们知道对象直接不能直接相加减,这时候就需借助运算符重载。

要重载运算符,可给类添加运算符类型成员(它们必须是static)。一些运算符有多种用途(如-运算符就有一元和二元两种功能),因此我们还指定了要处理多少个操作数, 以及这些操作数的类型。一般情况下,操作数的类型与定义运算符的类相同,但也可以定义处理混合类型的运算符

public class AddClass1

{

public int val;

public static AddClass1 operator +(AddClass1 op1, AddClass1 op2)

{

AddClass1 returnVal = new AddClass1();

returnVal.val = op1.val + op2.val;

return returnVal;

}

}

这时候就可以使用

AddClass1 op3 = op1 + op2;

可以重载下述运算符:

一元运算符:+, -, !, ~, ++, --, true, false

二元运算符:+, -, *, /, %, &, |, ˆ, <<, >>

比较运算符:==, !=, <, >, <=, >=

如果重载true 和false 运算符,就可以在布尔表达式中使用类,例如,if(op1){}

不能重载赋值运算符,例如+=

2)IComparable和IComparer接口:

IComparable 和IComparer 接口是.NET Framework 中比较对象的标准方式。这两个接口之间的差别如下:

IComparable 在要比较的对象的类中实现,可以比较该对象和另一个对象。

IComparer 在一个单独的类中实现,可以比较任意两个对象。

一般使用IComparable 给出类的默认比较代码,使用其他类给出非默认的比较代码。

IComparable 提供了一个方法CompareTo(),这个方法接受一个对象。例如,实现可以为实现方法传送一个Person 对象,以便确定这个人是否比当前的人更年老还是更年轻。实际上,这个方法返回一个int,所以也可以确定第二个人与当前的人的年龄差:

if (person1.CompareTo(person2) == 0)

{

Console.WriteLine("Same age");

}

else if (person1.CompareTo(person2) > 0)

{

Console.WriteLine("person 1 is Older");

}

else

{

Console.WriteLine("person1 is Younger");

}

IComparer 也提供了一个方法Compare()。这个方法接受两个对象,返回一个整型结果,这与CompareTo()相同。对于支持IComparer 的对象,可以使用下面的代码:

if (personComparer.Compare(person1, person2) == 0)

{

Console.WriteLine("Same age");

}

.NET Framework 在类Comparer 上提供了IComparer 接口的默认实现方式,类Comparer 位于System.Collections 名称空间中,可以对简单类型以及支持IComparable 接口的任意类型进行特定文化的比较。

int firstNumber = 35;

int secondNumber = 23;

Console.WriteLine("Comparing ‘{0}’ and ‘{1}’, result: {2}",

firstNumber, secondNumber,

Comparer.Default.Compare(firstNumber, secondNumber));

拓展:

可以使用as 运算符把一个值转换为引用类型。如果不能进行转换,as 运算符就返回null 值。

as 运算符使用下面的语法,把一种类型转换为指定的引用类型:

<operand> as <type>

这只适用于下列情况:

<operand>的类型是<type>类型

<operand>可以隐式转换为<type>类型

<operand>可以封箱到<type>类型中

如果不能从<operand>转换为<type>,则表达式的结果就是null。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值