比较
类型比较:比较对象时,常需了解它们的类型,才能确定是否可进行值的比较
可将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/