17.比较

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();
        }

猜你喜欢

转载自www.cnblogs.com/lidaying5/p/10595526.html