运算符和强制类型转换

本文详细介绍了 C# 中的运算符使用方法,包括特殊运算符 check 和 uncheck 的作用,is 和 as 运算符的区别,以及 sizeof 和 type 运算符的应用场景。同时深入探讨了 C# 中的类型转换机制,如隐式和显式转换、装箱与取消装箱技术,并介绍了如何在引用类型之间进行类型转换。
摘要由CSDN通过智能技术生成
本文主要介绍一下C#中的运算符和类型强制转换,主要内容包括
1.C#中的可用运算符
2.处理引用类型和值类型时相等的含义
3.基本数据类型之间的数据转换
4.装箱和开箱技术
5.通过强制转换技术在引用类型之间转换
6.运算符重载
7.自定义类型强制转换
下面详细介绍这7点内容

一、C#中的可用运算符
C#中的运算符跟c语言中的差不多,这里介绍几个特殊的运算符
1.1 check和uncheck运算符
      如果把一个代码块标记为checked,CLR就会执行溢出检查,如果发生溢出,就抛出异常。如果要禁止溢出检查,可以把代码标记为unchecked。unchecked是默认值。
None.gif // 运行下面这段代码,就会抛出异常
None.gif
byte  b = 255 ;
None.gif
checked
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  b
++;
ExpandedBlockEnd.gif}

None.gifConsole.WriteLine(b.ToString());
None.gif
None.gif
// 运行下面这段代码,则不会抛出异常
None.gif
byte  b = 255 ;
None.gif
unchecked
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  b
++;
ExpandedBlockEnd.gif}

None.gifConsole.WriteLine(b.ToString());

1.2 is运算符
is运算符可以检查对象是否与特定的类型兼容。
None.gif int  i  =   10 ;
None.gif
if (i  is   object )
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  Console.WriteLine(
"i is an object");
ExpandedBlockEnd.gif}

1.3 as运算符
as运算符用于执行引用类型的显示类型转换。如果转换类型与指定的类型兼容,转换成功;如果不兼容,返回null
None.gif object  o1  =   " some string " ;
None.gif
object  o2  =   5 ;
None.gif
string  s1  =  o1  as   string ;   // s1="some string"
None.gif
string  s2  =  o2  as   string ;   // s2=null 

1.4 sizeof运算符
使用sizeof运算符可以确定堆栈中值类型需要的长度(单位字节):注意只能在不安全的代码中使用sizeof
例如:sizeof(int)

1.5 type运算符
返回一个表示特定类型的Type对象。
例如:typeof(string)返回表示System.String类型的Type对象。在使用反射动态查找对象信息时,这个运算很有效。

二、类型转换

2.1 隐式转换
只能从较小的整数类型隐式转换为较大的整数类型,不能从较大的整数类型隐式地转换为较小地整数类型。
无符号的变量可以转换为有符号的变量,只要无符号的变量值的大小在有符号的变量的范围之内即可。
例如:
None.gif byte  v1  =   10 ;
None.gif
byte  v2  =   23 ;
None.gif
long  total;
None.giftotal 
=  v1  +  v2; // v1、v2均隐式转换为long类型

2.2显示转换
在不能隐式转换的时候,可以显示执行这些转换。格式如下:
None.gif long  val  =   3000000000 ;
None.gif
int  i  =  ( int )val; // 编译不会报错
所有的显示数据类型转换都可能不安全,在应用程序中应包含处理可能失败的数据类型转换的代码。例如:try/catch等
显示转换有一些限制,值类型只能在数字、char类型和enum类型之间转换。不能直接把Boolean数据类型转换为其他类型,也不能把其他类型转换为Boolean数据类型。

2.3装箱和取消装箱
装箱可以把值类型转换成引用类型(boxing),取消装箱可以把引用类型转换成值类型(unboxing)
None.gif int  i  =   20 ;
None.gif
None.gif
object  o  =  i;   // boxing
None.gif

None.gif
int  j  =  ( int )o;  // unboxing

三、对象的相等比较

3.1 引用类型的相等比较
有四种方法:
1)ReferenceEquals()方法
      ReferenceEquals()方法是一个静态方法,不能重写,只能使用System.object实现。如果提供的两个引用指向同一个对象实例,ReferenceEquals()方法
返回true,否则返回false。但是该方法认为null等于null。
None.gif SomeClass x,y;
None.gif
=   new  SomeClass();
None.gif
=   new  SomeClass();
None.gif
bool  B1  =  ReferenceEquals( null , null ); //  return true;
None.gif
bool  B2  =  ReferenceEquals( null ,x); //  return false;
None.gif
bool  B3  =  ReferenceEquals(x,y); //  return false because x and y point to different objects;

2)虚拟的Equals()方法
      Equals()方法是虚拟的,所以可以在自己的类中重写。
3)静态的Equals()方法
      静态的Equals()方法和虚拟的Equals()方法作用相同,区别是静态版本带有两个参数。静态方法可以处理两个对象中有一个是null的情况。
4)比较运算符==
      ==可以看作是严格值比较和严格引用比较之间的中间选项,使用时最好重写==运算符

3.2 值类型的相等比较
      值类型的相等比较与引用类型的相等比较采用相同的规则,最大的区别就是值类型需要装箱,才能执行上面介绍的四种方法。

四、运算符重载

 4.1 算术运算符重载    例如:
None.gif // 定义结构Vector
None.gif
struct  Vector
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
public double x,y,z;
InBlock.gif  
public Vector(double x,double y,double z)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
this.x = x;
InBlock.gif    
this.y = y;
InBlock.gif    
this.z = z;
ExpandedSubBlockEnd.gif  }

InBlock.gif  
public Vector(Vector rhs)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
this.x = rhs.x;
InBlock.gif    
this.y = rhs.y;
InBlock.gif    
this.z = rhs.z;
ExpandedSubBlockEnd.gif  }

InBlock.gif  
public override string ToString()
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
return "(" + x + "," + y + "," + z + ")";
ExpandedSubBlockEnd.gif  }

InBlock.gif  
//重载+运算符
InBlock.gif
  public static Vector operator + (Vector lhs, Vector rhs)//C#要求所有的运算符重载都声明为public和static
ExpandedSubBlockStart.gifContractedSubBlock.gif
  dot.gif{
InBlock.gif    Vector result 
= new Vector(lhs);
InBlock.gif    result.x 
+= rhs.x;
InBlock.gif    result.y 
+= rhs.y;
InBlock.gif    result.z 
+= rhs.z;
InBlock.gif    
return result;
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gif
// 测试
None.gif
static  Main()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  Vector vect1,vect2,vect3;
InBlock.gif  vect1 
= new Vector(3.0,3.0,1.0);
InBlock.gif  vect2 
= new Vector(2.0,-4.0,-4.0);
InBlock.gif  vect3 
= vect1 + vect2;
InBlock.gif  Console.WriteLine(
"vect1=" + vect1.ToString());
InBlock.gif  Console.WriteLine(
"vect2=" + vect2.ToString());
InBlock.gif  Console.WriteLine(
"vect3=" + vect3.ToString());
ExpandedBlockEnd.gif}

None.gif
None.gif
// 编译运行,结果如下:
None.gif
vect1 = ( 3 , 3 , 1 )
None.gifvect2
= ( 2 , - 4 , - 4 )
None.gifvect3
= ( 5 , - 1 , - 3 )
注意:C#不允许重载=运算符,但如果重载+运算符,编译器就会自动使用+运算符的重载来执行+=运算符的操作。-=、&=、*=、/=也遵循此规则

4.2 比较运算符重载
1)C#要求成对重载比较运算符(==和!=、>和<、>=和<=共3对),如果不成对重载,编译就会出错。
2)必须返回bool类型的值。
注意:重载==和!=时,还应重载System.object的Equals()方法和GetHashCode()方法,否则产生一个编译警告。因为Equals()方法执行与==相同的相等逻辑。
除此之外,比较运算符重载跟算术运算符的重载没有区别。

五、用户定义的数据类型转换

用户定义的数据类型转换和预定义的数据类型转换一样,也分隐式转换和显示转换两种。
如果知道无论在源变量中存储什么值,数据类型转换总是安全的,就可以用隐式转换;
如果某些数据值可能会出错,就应该把数据类型转换定义为显示的。
定义数据类型的转换类似于运算符重载:
None.gif public   static   implicit   operator   float (Currency value)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
//processing
ExpandedBlockEnd.gif
}
执行用户类型转换的完整示例:
None.gif struct  Currency
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
public uint Dollars;
InBlock.gif  
public ushort Cents;
InBlock.gif  
public Currency(uint dollars, ushort cents)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
this.Dollars = dollars;
InBlock.gif    
this.Cents = cents;
ExpandedSubBlockEnd.gif  }

InBlock.gif  
public override string ToString()
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
return string.Format("${0}.{1,-2.00}",Dollars,Cents);
ExpandedSubBlockEnd.gif  }

InBlock.gif  
//隐式转换
InBlock.gif
  public static operator float(Currency value)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
return value.Dollars + (value.Cents/100.0f
InBlock.gif);
InBlock.gif  
//显示转换
InBlock.gif
  public static operator Currency(float value)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
uint dollars = (uint)value;
InBlock.gif    
ushort cents = (ushort)((value-dollars)*100);
InBlock.gif    
return new Currency(dollars,cents);
ExpandedSubBlockEnd.gif  }

ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gif
// 测试
None.gif
static  Main()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  Currency balance 
= new Currency(50,35);
InBlock.gif  Console.WriteLine(balance);
InBlock.gif  Console.WriteLine(
"balance is " + balance);
InBlock.gif  Console.WriteLine(
"balance is (using ToString())" + balance.ToString());
InBlock.gif  
float balance2 = balance;
InBlock.gif  Console.WriteLine(
"After converting to float," + balance2);
InBlock.gif  balance 
= (Currency)balance2;
InBlock.gif  Console.WriteLine(
"After converting back to currency," + balance);
ExpandedBlockEnd.gif}

None.gif
None.gif
// 结果
None.gif
50.35
None.gifbalance 
is  $ 50.35
None.gifbalance 
is  ( using  ToString()) $ 50.35
None.gifAfter converting to 
float , 50.35
None.gifAfter converting back to currency,$
50.34 "  

5.1 类之间的数据类型转换
     两个限制:
     1)如果某个类直接或间接继承了另一个类,就不能在这两个类之间进行数据类型转换。
     2)数据类型转换必须在源或者目标数据类型定义的内部定义。

5.2 基类和派生类之间的数据转换       
None.gif // 类MyDerived派生于类MyBase
None.gif
  MyDerived derivedObject  =   new  MyDerived();
None.gif  MyBase baseCopy 
=  derivedObject; // 隐式转换
None.gif

None.gif  MyBase baseObject 
=   new  MyBase();
None.gif  MyDerived derivedCopy 
=  (Myderived)baseObject; // 抛出异常
None.gif

5.3 装箱和取消装箱数据类型转换
      值类型到object的转换是隐式转换 ,即装箱     
None.gif Curency banlance  =   new  Currency( 40 , 10 );
None.gif
object  baseCopy  =  banlance; // 隐式转换
     object到值类型的转换是显示转换,即取消装箱
None.gif object  derivedObject  =   new  Currency( 40 , 10 );
None.gif
object  baseObject  =   new   object ();
None.gifCurrency derivedCopy1 
=  (Currency)derivedObject; // OK
None.gif
Currency derivedCopy2  =  (Currency)baseObject; // 抛出异常

5.4 多重数据类型转换
     
None.gif Currency balance  =   new  Currency( 40 , 10 );
None.gif
long  amount  =  ( long )balance; // Currency->float->long
None.gif
double  amountD  =  balance; // Currency->float->double

转载于:https://www.cnblogs.com/justnow/archive/2007/01/31/631548.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值