C#入门经典(第五版)学习笔记(五)

比较
类型比较:比较对象时,常需了解它们的类型,才能确定是否可进行值的比较
可将GetType()方法和typeof()运算符一起使用,例如:if(myObj.GetType()==typeof(MyComplexClass)){ }
封箱和拆箱
封箱是把值类型转换为System.Object类型,或转换为由值类型实现的接口类型。拆箱则相反。
例如这个结构类型:
struct MyStruct
{
    public int Val;
}
进行封箱
MyStruct valType1 = new MyStruct();
valType1.Val = 5;
object refType = valType1;   //封箱
但此时封箱创建的对象refType,其实是值类型变量的一个副本的引用。比如此时更改值类型变量的内容,封箱的对象内的值并不会随之改变。
例如:
valType1.Val = 6;
MyStruct valType2 = (MyStruct)refType;    //拆箱
Console.WriteLine("valType1.Val = {0}",valType1.Val);
Console.WriteLine("valType2.Val = {0}",valType2.Val);
此时这段代码将输出如下结果:
valType1.Val = 6
valType2.Val = 5
但如果将一个引用类型进行此类操作时,可以看到如下结果
class MyClass
{
    public int Val;
}
MyClass valType1 = new MyClass();
valType1.Val = 5;
object refType = valType1;    //封箱特指从值类型变量转为引用类型变量,所以这句并不是封箱。
valType1.Val = 6;
MyClass valType2 = (MyClass)refType;
Console.WriteLine("valType1.Val = {0}",valType1.Val);
Console.WriteLine("valType2.Val = {0}",valType2.Val);
输出结果:
valType1.Val = 6
valType2.Val = 6
另外,也可以把值类型变量封箱到一个接口类型中(必须要实现这个接口才行),例如:
interface IMyInterface
{}
struct MyStruct : IMyInterface
{
    public int Val;
}
MyStruct valType1 = new MyStruct();
valType1.Val = 5;
IMyInterface refType = valType1;   //封箱
MyStruct valType2 = (MyStruct)refType    //拆箱
比较值更简便的是运算符is。它的可读性更高,还可以检查基类,语法如下:
is
1 如果是一个类类型,也是该类型,或继承了该类型,或封箱到该类型中,则返回true
2 如果是一个接口类型,也是该类型,或是实现该接口的类型,则返回true
3 如果是一个值类型,也是该类型,或封箱到该类型中,则返回true

值比较
运算符重载
要重载运算符,可给类添加运算符类型成员(它们必须是static)。有些运算符有多重用途(如-运算符就有一元和二元两种功能),所以我们还得制定要处理多少个操作数,以及操作数的类型。
Public class Class1
{
    public int val;
}
Class1 op1 = new Class1();
op1.val = 5;
Class1 op2 = new Class1();
op2.val = 5;
如果没有进行运算符重载,那下面这句就无法编译
Class1 op3 = op1 + op2;
使用下述代码对运算符+进行重载:
public class Class1
{
    public int val;

    public static Class1 operator +(Class1 op1,Class1 op2)
    {
        Class1 returnVal = new Class1();
        returnVal.val = op1.val + op2.val;
        return returnVal;
    }
}
此时Class1 op3 = op1 + op2就可以通过编译,通过Console.WriteLine(op3.val);可得到结果10.
重载一元运算符类似,但只有一个参数
public static Class1 operator -(Class1 op1)
{
    Class1 returnVal = new Class1();
    returnVal.val = - op1.val;
    return returnVal;
}
也可以对混合类型进行重载运算符,例如:
public class Class1
{
    public int val;

    public static Class3 operator +(Class1 op1,Class2 op2)
    {
        Class3 returnVal = new Class3();
        returnVal.val = op1.val + op2.val;
        return returnVal;
    }
}
public class Class2
{
    public int val;
}
public class Class3
{
    public int val;
}
执行下面的代码
Class1 op1 = new Class1();
op1.val = 5;
Class2 op2 = new Class2();
op2.val = 6;
Class3 op3 = op1 + op2;
Console.WriteLine(op3.val);    //结果输出11
这种方式混合类型可酌情使用,但要注意,不能把相同的运算符添加到Class2中,否则编译器弄不清要使用哪个运算符。
而且需要注意,操作数的顺序必须和运算符重载的参数顺序相同,否则编译器也无法通过,除非提供了如下的另一个重载运算符
public static Class3 operator +(Class2 op2,Class1 op1)
{
    Class3 returnVal = new Class3();
    returnVal.val = op2.val + op1.val;
    return returnVal;
}
可以重载的运算符有:
一元运算符:+,-,!,~,++,--,true,false
二元运算符:+,-,*,/,%,&,|,^,<>
比较运算符:==,!=,,<=,>=
有些运算符如必须成对重载,许多情况下,可以在这些重载这些运算符时调用其他运算符,以减少代码量,而且日后更改方便
public class class1
{
    public int val;
    public static class1 operator>=(class1 op1,class1,op2)
    {
        return (op1.val >= op2.val);
    }
    public static class1 operator     {
        return !(op1 >= op2);
    }
}
这同样适用于==和!=,但如果重载了==和!=,也应重写Object.Equals()和Object.GetHashCode(),因为这两个函数也可以用于比较对象。
它们需要下述非静态重写方法:
public override bool Equals(object op1)
{
    if(op1 is Class1)    //如需对类型完全相同的两个对象进行比较,可用if(op1.GetType() == typeof(Class1))
        return val == ((Class1)op1).val;
    else
        throw new ArgumentException("cannot compare Class1 objects with objects of type" + op1.GetType().ToString());
}
public override int GetHashCode()
{
    return val;
}

IComparable和IComparer接口
IComparable提供一个CompareTo()方法比较两个对象,并返回一个int值
例如:
    class Person : IComparable
    {
        public string Name;
        public int Age;

        public Person(string name, int age)
        {
            Name = name;
            Age = age;
        }

        public int CompareTo(object obj)
        {
            if (obj is Person)
            {
                Person otherPerson = obj as Person;
                return this.Age - otherPerson.Age;
            }
            else
            {
                throw new ArgumentException( "Object to compare to is not a Person object.");
            }
        }
    }

主程序代码
    class Program
    {
        static void Main(string[] args)
        {
            Person person1 = new Person("Jim", 30);
            Person person2 = new Person("Bob", 25);

            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()方法,接受两个对象返回一个整型结果
例如:
    public class PersonComparer : IComparer
    {
        public static IComparer Default = new PersonComparer();

        public int Compare(object x, object y)
        {
            if (x is Person && y is Person)
            {
                return Comparer.Default.Compare(((Person)x).Age, ((Person)y).Age);
            }
            else
            {
                throw new ArgumentException(
                   "One or both objects to compare are not Person objects.");
            }
        }
    }

主程序:
    class Program
    {
        static void Main(string[] args)
        {
            Person person1 = new Person("Jim", 30);
            Person person2 = new Person("Bob", 25);

            if (PersonComparer.Default.Compare(person1, person2) == 0)
            {
                Console.WriteLine("Same age");
            }
            else if (PersonComparer.Default.Compare(person1, person2) > 0)
            {
                Console.WriteLine("person 1 is Older");
            }
            else
            {
                Console.WriteLine("person1 is Younger");
            }
        }
    }
注意事项:
1.检查传送给Comparer.Compare()的对象,看看它们是否支持IComparable。如果支持,就使用该实现代码
2.允许使用null值,它表示“小于”其他对象。
3.字符串根据当前文化来处理。要根据不同的文化(或语言)处理字符串,Comparer类必须使用其构造函数进行实例化,以便传送指定所使用的文化的System.Globalization.CultureInfo对象
4.字符串在处理时要区分大小写。如果不需要区分,需使用CaseInsensitiveComparer类。

转换
重载转换运算符
用关键字implicit来指定隐式转换;用关键字explicit来指定显式转换
public class ConvClass1
{
    public int val;
    public static implicit operator ConvClass2(ConvClass1 op1)
    {
        ConvClass2 returnVal = new ConvClass2();
        returnVal.val = op1.val;
        return returnVal;
    }
}
public class ConvClass2
{
    public int val;
    public static explicit operator ConvClass1(ConvClass2 op1)
    {
        ConvClass1 returnVal = new ConvClass1();
        checked {returnVal.val = (int)op1.val;};
        return returnVal;
    }
}
as运算符
把一种类型转换为指定的引用类型,语法如下:
as
适用于下列情况:
1.的类型是类型
2.可以隐式转换为类型
3.可以封箱到类型中
如果不能从转换为,则表达式结果是null
例如:
class ClassA : IMyInterface
{
}
 
class ClassD : ClassA
{
}

ClassA obj1 = new ClassA();
ClassD obj2 = obj1 as ClassD;
obj2的结果是null
使用一般的类型转换,出错时会抛出一个异常
而as只会把null赋給对象,只要判断对象是否null就知道转换是否成功

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10663598/viewspace-1197185/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10663598/viewspace-1197185/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值