1.类型比较
使用GetType()和typeof()比较类型
AddClass1 c1 = new AddClass1(); if (c1.GetType() == typeof(AddClass1)) { //dosomething }
1.1.封箱和拆箱
封箱是指把值类型转换为System.Object类型,或者转换为由值类型实现的接口。
struct MyStruct { public int Val; } MyStruct valType1 = new MyStruct(); valType1.Val = 5; object refType = valType1;//把结构类型放在object类型的变量中以封箱它
注:以这种方式封装而创建的对象包含的是值类型的一个副本的引用,而不是包含源值类型的引用
valType1.Val = 6; MyStruct valType3 = (MyStruct)refType;//拆箱 Console.WriteLine(valType3.Val);//5
如果是把引用类型的对象赋值给Object 类型的变量则新变量包含的是源对象的引用,这取决于值类型和引用类型的存储的区别,因为值类型存储的是一个值,引用类型存储的是对象的地址。
值类型封装成它实现的接口
interface MyInterface { } struct MyStruct:MyInterface { public int Val; } MyStruct valType1 = new MyStruct(); valType1.Val = 5; MyInterface refType2 = valType1;
1.2.is运算符
is运算符可以检查对象是否是给定类型,或者可以转换为给定类型。
is运算符的语法如下:
<operand> is <type>
1) 如果type 是一个类类型,operand 也是该类型,或者operand 继承于该类型,或者它可以封箱到该类型,那么表达式的结果为true;
2)如果type是一个接口类型,operand也是该类型,或者operand实现了该接口,则表达式的结果为true;
2)如果type是一个值类型,operand也是该类型,或者operand可以拆箱为该类型,那么表达式的结果为true。
int i=0; Console.WriteLine(i is object);//true
2.值比较
2.1运算符重载
比较两个人的年龄可以像如下这样比较
if(pseron1.Age>person2.Age) { //dosomething }
但是如果要直接比较两个对象,就必须要在该对象的类中对运算符进行重载,以定义比较的规则。
class AddClass1 { public int Val; public static bool operator ==(AddClass1 c1, AddClass1 c2) { return c1.Val == c2.Val; } public static bool operator !=(AddClass1 c1, AddClass1 c2) { return !(c1 == c2); } public override bool Equals(object obj) { //return this.Val==((AddClass1)obj).Val; return this == (AddClass1)obj; } public override int GetHashCode() { return Val; } }
AddClass1 c1 = new AddClass1(); c1.Val = 5; AddClass1 c2 = new AddClass1(); c2.Val = 5; Console.WriteLine(c1 == c2);//true Console.WriteLine(c1.Equals(c2));//true
重载运算符必须成对进行,比如重载了==,就必须重载!=,重载了>,就必须重载<。可以在别的运算符中使用已重载的运算符。一般重载了==和!==运算符要一起重写Equals和GetHashCode方法,因为这两个方法也是用来做比较的,这样做能让用户不管怎么操作结果都一致。
注:不能重载赋值运算符=和复合赋值运算符,如+=,也不能重载&&和||,可以重载&和|。
2.2IComparable和IComparer接口
IComparable和 IComparer接口是.net提供的比较两个对象的标准方法,这两个方法是区别是:
1)IComparable接口要在需要比较的对象的类中实现,可以比较该对象和另一个对象;
2)IComparer接口在一个单独的类中实现,可以比较两个对象。
IComparable用来提供对象的默认比较方法,如果要提供其他比较方法一般新建一个类继承IComparer。对象集合排序时必须要提供默认比较方法实现,即继承IComparable接口,因为Sort()方法会调用默认的比较方法。也可以给Sort()方法传递一个实现IComparer接口的对象,以便用别的方法排序。
IComparable接口提供了一个CompareTo方法,该方法返回一个int 类型的数据,可以确定两个对象的差距有多大。IComparer 接口提供了Compare()方法,返回int类型的数据,其含义和CompareTo一样。
以下是比较两个对象的例子
public class Person:IComparable { public string Name { get; set; } public int Age { get; set; } [System.Xml.Serialization.XmlElementAttribute("Books")] public Books Books { get; set; } public Person(string name, int age) { Name = name; Age = age; } public int CompareTo(object obj) { return this.Age-((Person)obj).Age; } } public class PersonComparerName:IComparer { public static IComparer Default = new PersonComparerName(); public int Compare(object x, object y) { if (x is Person && y is Person) { return Comparer.Default.Compare(((Person)x).Name, ((Person)y).Name); } else throw new ArgumentException("One or both object to compare is not Person objects."); } } static void Main(string[] args) { ArrayList list = new ArrayList(); list.Add(new Person("Jim",30)); list.Add(new Person("Bob", 25)); list.Add(new Person("Bert", 27)); Console.WriteLine(((Person)list[0]).CompareTo((Person)list[1]));//Jim比Bob大5岁,所以返回5 Console.WriteLine(PersonComparerName.Default.Compare((Person)list[0],(Person)list[1]));//Jim 首字母J比Bob首字母排在后面,所以返回1 Console.WriteLine("原始数据"); foreach (object o in list) { Person p =(Person)o; Console.WriteLine("Name:{0},Age:{1}", p.Name, p.Age); } Console.WriteLine("默认排序"); list.Sort();//调用Person默认排序方法 foreach (object o in list) { Person p = (Person)o; Console.WriteLine("Name:{0},Age:{1}", p.Name, p.Age); } Console.WriteLine("按照名字排序"); list.Sort(PersonComparerName.Default); foreach (object o in list) { Person p = (Person)o; Console.WriteLine("Name:{0},Age:{1}", p.Name, p.Age); } Console.ReadLine(); } }
.net 提供了一个比较简单类型的类Comparer,我们可以直接使用它来比较简单类型的数据。一般比较的结果为-1 、0 、1.
static void Main(string[] args) { string firstString = "First string"; string secondString = "Second string"; string thirdString = "First string"; //因为F在字母表中排在S前面,所以第一个比较结果是-1 Console.WriteLine("Comparing {0} and {1} ,result:{2}", firstString, secondString, Comparer.Default.Compare(firstString, secondString)); //第一个和第三个字符串一样,结果返回0 Console.WriteLine("Comparing {0} and {1} ,result:{2}", firstString, thirdString, Comparer.Default.Compare(firstString, thirdString)); int firtNum = 12; int secondNum = 24; //12比24小,返回-1 Console.WriteLine("Comparing {0} and {1} ,result:{2}", firtNum, secondNum, Comparer.Default.Compare(firtNum, secondNum)); Console.ReadLine(); }