本文主要介紹一下C#中的運算符和類型強制轉換,主要內容包括
1.C#中的可用運算符
2.處理引用類型和值類型時相等的含義
3.基本數據類型之間的數據轉換
4.裝箱和開箱技術
5.通過強制轉換技術在引用類型之間轉換
6.運算符重載
7.自定義類型強制轉換
下面詳細介紹這7點內容
一、C#中的可用運算符
C#中的運算符跟c語言中的差不多,這里介紹幾個特殊的運算符
1.1 check和uncheck運算符
如果把一個代碼塊標記為checked,CLR就會執行溢出檢查,如果發生溢出,就拋出異常。如果要禁止溢出檢查,可以把代碼標記為unchecked。unchecked是默認值。
//運行下面這段代碼,就會拋出異常
byte b=255;
checked
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
b++;
}
Console.WriteLine(b.ToString());
![](http://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//運行下面這段代碼,則不會拋出異常
byte b=255;
unchecked
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
b++;
}
Console.WriteLine(b.ToString());
1.2 is運算符
is運算符可以檢查對象是否與特定的類型兼容。
int i = 10;
if(i is object)
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
Console.WriteLine("i is an object");
}
1.3 as運算符
as運算符用于執行引用類型的顯示類型轉換。如果轉換類型與指定的類型兼容,轉換成功;如果不兼容,返回null
object o1 = "some string";
object o2 = 5;
string s1 = o1 as string; //s1="some string"
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 隱式轉換
只能從較小的整數類型隱式轉換為較大的整數類型,不能從較大的整數類型隱式地轉換為較小地整數類型。
無符號的變量可以轉換為有符號的變量,只要無符號的變量值的大小在有符號的變量的范圍之內即可。
例如:
byte v1 = 10;
byte v2 = 23;
long total;
total = v1 + v2;//v1、v2均隱式轉換為long類型
2.2顯示轉換
在不能隱式轉換的時候,可以顯示執行這些轉換。格式如下:
long val = 3000000000;
int i = (int)val;//編譯不會報錯所有的顯示數據類型轉換都可能不安全,在應用程序中應包含處理可能失敗的數據類型轉換的代碼。例如:try/catch等
顯示轉換有一些限制,值類型只能在數字、char類型和enum類型之間轉換。不能直接把Boolean數據類型轉換為其他類型,也不能把其他類型轉換為Boolean數據類型。
2.3裝箱和取消裝箱
裝箱可以把值類型轉換成引用類型(boxing),取消裝箱可以把引用類型轉換成值類型(unboxing)
int i = 20;
![](http://www.cnblogs.com/Images/OutliningIndicators/None.gif)
object o = i; //boxing
![](http://www.cnblogs.com/Images/OutliningIndicators/None.gif)
int j = (int)o; //unboxing
三、對象的相等比較
3.1 引用類型的相等比較
有四種方法:
1)ReferenceEquals()方法
ReferenceEquals()方法是一個靜態方法,不能重寫,只能使用System.object實現。如果提供的兩個引用指向同一個對象實例,ReferenceEquals()方法
返回true,否則返回false。但是該方法認為null等于null。
SomeClass x,y;
x = new SomeClass();
y = new SomeClass();
bool B1 = ReferenceEquals(null,null);// return true;
bool B2 = ReferenceEquals(null,x);// return false;
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 算術運算符重載 例如:
//定義結構Vector
struct Vector
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
public double x,y,z;
public Vector(double x,double y,double z)
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.x = x;
this.y = y;
this.z = z;
}
public Vector(Vector rhs)
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.x = rhs.x;
this.y = rhs.y;
this.z = rhs.z;
}
public override string ToString()
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return "(" + x + "," + y + "," + z + ")";
}
//重載+運算符
public static Vector operator + (Vector lhs, Vector rhs)//C#要求所有的運算符重載都聲明為public和static
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Vector result = new Vector(lhs);
result.x += rhs.x;
result.y += rhs.y;
result.z += rhs.z;
return result;
}
}
![](http://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//測試
static Main()
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
Vector vect1,vect2,vect3;
vect1 = new Vector(3.0,3.0,1.0);
vect2 = new Vector(2.0,-4.0,-4.0);
vect3 = vect1 + vect2;
Console.WriteLine("vect1=" + vect1.ToString());
Console.WriteLine("vect2=" + vect2.ToString());
Console.WriteLine("vect3=" + vect3.ToString());
}
![](http://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//編譯運行,結果如下:
vect1=(3,3,1)
vect2=(2,-4,-4)
vect3=(5,-1,-3)注意:C#不允許重載=運算符,但如果重載+運算符,編譯器就會自動使用+運算符的重載來執行+=運算符的操作。-=、&=、*=、/=也遵循此規則
4.2 比較運算符重載
1)C#要求成對重載比較運算符(==和!=、>和<、>=和<=共3對),如果不成對重載,編譯就會出錯。
2)必須返回bool類型的值。
注意:重載==和!=時,還應重載System.object的Equals()方法和GetHashCode()方法,否則產生一個編譯警告。因為Equals()方法執行與==相同的相等邏輯。
除此之外,比較運算符重載跟算術運算符的重載沒有區別。
五、用戶定義的數據類型轉換
用戶定義的數據類型轉換和預定義的數據類型轉換一樣,也分隱式轉換和顯示轉換兩種。
如果知道無論在源變量中存儲什么值,數據類型轉換總是安全的,就可以用隱式轉換;
如果某些數據值可能會出錯,就應該把數據類型轉換定義為顯示的。
定義數據類型的轉換類似于運算符重載:
public static implicit operator float(Currency value)
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
//processing
}執行用戶類型轉換的完整示例:
struct Currency
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
public uint Dollars;
public ushort Cents;
public Currency(uint dollars, ushort cents)
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.Dollars = dollars;
this.Cents = cents;
}
public override string ToString()
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return string.Format("${0}.{1,-2.00}",Dollars,Cents);
}
//隱式轉換
public static operator float(Currency value)
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return value.Dollars + (value.Cents/100.0f
);
//顯示轉換
public static operator Currency(float value)
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
uint dollars = (uint)value;
ushort cents = (ushort)((value-dollars)*100);
return new Currency(dollars,cents);
}
}
}
![](http://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//測試
static Main()
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
Currency balance = new Currency(50,35);
Console.WriteLine(balance);
Console.WriteLine("balance is " + balance);
Console.WriteLine("balance is (using ToString())" + balance.ToString());
float balance2 = balance;
Console.WriteLine("After converting to float," + balance2);
balance = (Currency)balance2;
Console.WriteLine("After converting back to currency," + balance);
}
![](http://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//結果
50.35
balance is $50.35
balance is (using ToString()) $50.35
After converting to float,50.35
After converting back to currency,$50.34"
5.1 類之間的數據類型轉換
兩個限制:
1)如果某個類直接或間接繼承了另一個類,就不能在這兩個類之間進行數據類型轉換。
2)數據類型轉換必須在源或者目標數據類型定義的內部定義。
5.2 基類和派生類之間的數據轉換
//類MyDerived派生于類MyBase
MyDerived derivedObject = new MyDerived();
MyBase baseCopy = derivedObject;//隱式轉換
![](http://www.cnblogs.com/Images/OutliningIndicators/None.gif)
MyBase baseObject = new MyBase();
MyDerived derivedCopy = (Myderived)baseObject;//拋出異常
![](http://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5.3 裝箱和取消裝箱數據類型轉換
值類型到object的轉換是隱式轉換 ,即裝箱
Curency banlance = new Currency(40,10);
object baseCopy = banlance;//隱式轉換 object到值類型的轉換是顯示轉換,即取消裝箱
object derivedObject = new Currency(40,10);
object baseObject = new object();
Currency derivedCopy1 = (Currency)derivedObject;//OK
Currency derivedCopy2 = (Currency)baseObject;//拋出異常
5.4 多重數據類型轉換
Currency balance = new Currency(40,10);
long amount = (long)balance;//Currency->float->long
double amountD = balance;//Currency->float->double