泛型与操作符重载杂谈
泛型基礎(chǔ)
1.為什么要用泛型類,我們先來看一段代碼:
以交換兩個(gè)數(shù)為例,可能需要定義多個(gè)重載方法
public static void swap(ref int x,ref int y)
{
int temp = x;x=y;y=temp;
}
public static void swap(ref float x,ref float y)
{
float temp = x;x=y;y=temp;
}
public static void swap(ref double x,ref double y)
{
double temp = x;x=y;y=temp;
}
這些方法的實(shí)現(xiàn)代碼類似,只是操作的數(shù)據(jù)類型不同而已,這種方法雖然沒錯(cuò),但工作效率低,可維護(hù)性差。一但發(fā)現(xiàn)錯(cuò)誤,就不得不在個(gè)個(gè)地方重復(fù)修改。于是有人就會(huì)提出一種新的方法,既然C#中object類是其他任何類的基類,那么把方法中的參數(shù)類型改為object類型,不就可以交換任何類型的值了?
public static void swap(ref object x,ref object y)
{
object temp = x;x=y;y=temp;
}
這種方法雖然有可取之處,但又會(huì)帶來新的麻煩,因?yàn)槿绻麑?duì)值類型調(diào)用此方法,程序需要在值類型與object類之間進(jìn)行裝箱和拆箱的轉(zhuǎn)換,頻繁使用會(huì)大大降低程序的性能,另外,如果用戶試圖交換兩個(gè)不同類型的值(例如一個(gè)×××,一個(gè)字符串),但這兩種類型是不能交換的,程序能通過編譯,但運(yùn)行時(shí)會(huì)出錯(cuò)。
我們來看下面的代碼:
using System;
namespace p9
{
public class abc
{
public static void Main()
{
int a = 10,b = 20;double c = 0.3,d = 1.25;string e = "我愛";string f ="你們";
fanxing<int>.swap(ref a,ref b);
fanxing<double>.swap(ref c,ref d);
Console.WriteLine("{0} {1},{2} {3},{4}{5}",a,b,c,d,e,f);
}
}
public class fanxing<T>
{
public static void swap(ref T x,ref T y)
{
T temp=x;x=y;y=temp;
}
}
}
上面定義的fanxing<T>就是一個(gè)泛型類,<>中的T被稱為類型參數(shù),類型參數(shù)T可以被不同的具體類型所替代(泛型類中每一個(gè)T都將被相應(yīng)類型替代),fanxing<int>等被稱為泛型類的構(gòu)造類型。在Main()方法中,如: fanxing<int>.swap(ref a,ref b); 使用的不是泛型類本身,而是泛型類的構(gòu)造類型fanxing<int>,泛型類的構(gòu)造類型和其他類一樣可以通過類型名來調(diào)用其靜態(tài)成員,或使用new來創(chuàng)建對(duì)象,并通過對(duì)象來調(diào)用其實(shí)例成員。
2.泛型的靜態(tài)成員
就如其他普通類中的靜態(tài)成員(字段和方法)只能被類名(不是類的實(shí)例)調(diào)用一樣,泛型類中的靜態(tài)成員也只能被靜態(tài)類的構(gòu)造類名(不是泛型類名)調(diào)用。如果上述代碼中出現(xiàn)以下代碼就會(huì)出錯(cuò):fanxing<int> a = new fanxing<int>(); a.swap(ref a,ref b); fanxing<T>.swap(ref a,ref b);
對(duì)于普通類,一個(gè)靜態(tài)字段在內(nèi)存中最多只有一個(gè)備份,對(duì)于泛型類,為其創(chuàng)建了多少種(不是多少個(gè))構(gòu)造類型,一個(gè)靜態(tài)字段就在內(nèi)存中有多少份備份。和普通類的靜態(tài)構(gòu)造函數(shù)在類創(chuàng)建實(shí)例時(shí)先于其他構(gòu)造函數(shù)執(zhí)行且只執(zhí)行一次一樣,泛型類的靜態(tài)構(gòu)造函數(shù)也先于其他構(gòu)造函數(shù)執(zhí)行,不同的是對(duì)于不同類型的構(gòu)造類型(每種構(gòu)造類型)都要調(diào)用一次靜態(tài)構(gòu)造函數(shù),而對(duì)于其他構(gòu)造函數(shù),每一種構(gòu)造類型有幾個(gè)構(gòu)造類型就調(diào)用幾次構(gòu)造函數(shù)。不同類型的構(gòu)造類型之間不互相影響。如下代碼:
using System
namespace p
{
public class abc
{
public static void Main()
{
Contact<int> c1 = new Contact<int>("趙麗");
Contact<int> c2 = new Contact<int>("湯姆");
Contact<double> c3 = new Contact<double>("李明"); }
}
}
public class Contact<T>
{
private string m_name;
private static int m_objects = 0;
private static int m_classes = 0;
public Contact (string name)
{
Console.WriteLine("構(gòu)造對(duì)象:"+name);
m_name = name;
m_objects++;
Console.WriteLine("Contact<{0}>對(duì)象數(shù)量:{1}",typeof(T),m_objects);
}
static Contact()
{
Console.WriteLine("構(gòu)造類Contact<{0}>",typeof(T));
m_classes++;
Console.WriteLine("Contact<{0}>類數(shù)量:{1}",typeof(T),m_classes);
}
}
輸出結(jié)果為:
構(gòu)造類Contact<System.Int32>
Contact<System.Int32>類數(shù)量:1
構(gòu)造對(duì)象:趙麗
Contact<System.Int32>對(duì)象數(shù)量:1
構(gòu)造對(duì)象:湯姆
Contact<System.Int32>對(duì)象數(shù)量:2
構(gòu)造類Contact<System.Double>
Contact<System.Double>類數(shù)量:1
構(gòu)造對(duì)象:李明
Contact<System.Double>對(duì)象數(shù)量:1
操作符重載
重載操作符的意思就是,重新定義該操作符的運(yùn)算方法,類似于聲明一個(gè)方法,也有形式參數(shù)。重載操作符要用到關(guān)鍵字operator。C#中重載操作符的語(yǔ)法是: public static 返回類型 operator 操作符 (形式參數(shù))。注意:重載運(yùn)算符時(shí),必須用到public和static關(guān)鍵字,并且形式參數(shù)不能為空。
重載一元操作符
可重載的一元操作符有: + - ! ~ ++ -- true false (其中true與false的重載必須同時(shí)出現(xiàn),且返回值類型是bool)
using System;
class BooleanInt
{
private int i;
public int Int
{
get {return i;}
set {i = value;}
}
public BooleanInt()
{}
public BooleanInt(int i)
{Int = i;}
public BooleanInt(BooleanInt bi)
{Int = bi.Int;}
public static BooleanInt operator +(BooleanInt bi)
{return new BooleanInt(bi.Int);}
public static BooleanInt operator -(BooleanInt bi)
{return new BooleanInt(-bi.Int);} // @@@@@
public static bool operator !(BooleanInt bi)
{if (bi.Int ==0)
return true;
return false;}
public static BooleanInt operator~(BooleanInt bi)
{return new BooleanInt( ~bi.Int);}
public static BooleanInt operator ++(BooleanInt bi)
{return new BooleanInt(++bi.Int);}
public static BooleanInt operator --(BooleanInt bi)
{return new BooleanInt(--bi.Int);}
public static bool operator true(BooleanInt bi)
{
if (bi.Int==0)
return false;
return true;
}
public static bool operator false(BooleanInt bi)
{
if (bi.Int==0)
return true;
return false;
}
}
class Test
{
public static void Main()
{
BooleanInt bi = new BooleanInt(10);
Console.WriteLine("bi:{0}",bi.Int);
bi=+bi;
Console.WriteLine("+bi:{0}",bi.Int);
bi=-bi;
Console.WriteLine("-bi:{0}",bi.Int);
Console.WriteLine("!bi:{0}",!bi);
Console.WriteLine("!!bi:{0}",!!bi);
bi=~bi;
Console.WriteLine("~bi:{0}",bi.Int);
BooleanInt newBi = ++bi;
Console.WriteLine("newBi = ++bi:{0},{1}",newBi.Int,bi.Int);
newBi = --bi;
Console.WriteLine("newBi = --bi:{0},{1}",newBi.Int,bi.Int);
bi = new BooleanInt(1);
if (bi) //調(diào)用true重載
Console.WriteLine("true - BooleanInt(1):true");
else
Console.WriteLine("true - BooleanInt(1):false");
bi =new BooleanInt(0);
if (bi) //也是調(diào)用true重載,只是true操作符的重載必須也同樣有false操作符的重載
Console.WriteLine("false - BooleanInt(0):true");
else
Console.WriteLine("false - BooleanInt(0):false");
Console.Read();
}
}
輸出結(jié)果:
bi:10
+bi:10
-bi:-10
!bi:False
!!bi:True
~bi:9
newBi = ++bi:10,10
newBi = --bi:9,9
true - BooleanInt(1):true
false - BooleanInt(0):false
@@@@@處,return new BooleanInt(-bi.Int); 等同于 BooleanInt a =new BooleanInt(-bi.Int);return a; 就是說先創(chuàng)造一個(gè)類的實(shí)例,同時(shí)調(diào)用該類的構(gòu)造函數(shù),再返回該類的對(duì)象,返回值取決于BooleanInt類的ToString()方法的字符串返回值。 例如一下代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(abc.xie());
Console.ReadLine();
}
}
public class abc
{
public override string ToString() // ToString()是object類的一個(gè)方法,每個(gè)類都繼承了該方法,如果子類不重寫該方法,該方法返回的是當(dāng)前類名的字符串形式。
{
Console.Write("ToString()方法用于將數(shù)值轉(zhuǎn)換成字符串,本例為:");
return 123.ToString();
}
public abc(int a)
{
Console.WriteLine("return a,返回對(duì)象取決于該對(duì)象的ToString()方法");
}
public static abc xie()
{
abc a = new abc(1);
return a;
}
}
}
輸出結(jié)果為:
return a,返回對(duì)象取決于該對(duì)象的ToString()方法
ToString()方法用于將數(shù)值轉(zhuǎn)換成字符串,本例為:123
如果把return 123.ToString();改為return base.ToString(); 那么輸出結(jié)果為:
return a,返回對(duì)象取決于該對(duì)象的ToString()方法
ToString()方法用于將數(shù)值轉(zhuǎn)換成字符串,本例為: ConsoleApplication1.abc
也就是說ToString()方法前面有兩種參數(shù),一是簡(jiǎn)單值類型(這時(shí)是將簡(jiǎn)單值類型轉(zhuǎn)換為字符串形式),一是base(這時(shí)base指的是基類,在此就是object類,而object類定義的 ToString()方法返回的是當(dāng)前類名的字符串形式)
重載二元操作符
可重載的二元操作符有: + - * / % & | ^ << >> == != > < >= <= (其中==與!= >與< >=與<=的重載必須同時(shí)出現(xiàn),如果重載了==與!=,最好同時(shí)重載Equals(),而這又需要重載GetHashCode()。如果重載了 + - * / % & | ^ << >>,那么也就重載了對(duì)應(yīng)的復(fù)合值操作符 += -= *= /= %= &= |= ^= <<= >>=)
例如一下代碼:
using System;
class BooleanInt
{
private int i;
public int Int
{
get{return i;}
set{i = value;}
}
public BooleanInt(){}
public BooleanInt(int i)
{Int = i;}
public BooleanInt(BooleanInt bi)
{Int = bi.Int;}
public static BooleanInt operator +(BooleanInt bi1,BooleanInt bi2)
{return new BooleanInt(bi1.Int + bi2.Int);}
public static BooleanInt operator -(BooleanInt bi1,BooleanInt bi2) //@
{return new BooleanInt(bi1.Int + bi2.Int);} /@@
public static bool operator ==(BooleanInt bi1,BooleanInt bi2)
{return bi1.Int==bi2.Int; }
public static bool operator !=(BooleanInt bi1, BooleanInt bi2)
{ return bi1.Int != bi2.Int; }
public override bool Equals(object obj)
{
return base.Equals(obj); //雖然是重載了,但等于沒重載,因?yàn)閮?nèi)部仍然用的是基類(這里是object類)的Equals()方法,不過這樣不會(huì)出現(xiàn)警告。
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
class test
{
public static void Main()
{
BooleanInt bi1 = new BooleanInt(8);
BooleanInt bi2 = new BooleanInt(2);
Console.WriteLine("bi1:{0} bi2:{1}",bi1.Int,bi2.Int);
BooleanInt bi = bi1 + bi2;
Console.WriteLine("bi1 + bi2 ={0}",bi.Int);
bi -= bi1; //由于上面@處重載了-,所以-=也被相應(yīng)的重載了。
Console.WriteLine("bi -= bi1:{0}",bi.Int); //驗(yàn)證了,重載是重新定義操作符的算法,@@處雖然重載了-,但重載的算法是加法。
Console.WriteLine("bi!=bi1:{0}",bi!=bi1);
Console.Read();
}
}
重載轉(zhuǎn)換運(yùn)算符
語(yǔ)法: public static (implicit|explicit) operator 返回類型(當(dāng)前類名 變量){具體轉(zhuǎn)換}
implicit聲明轉(zhuǎn)換符為隱式 explicit聲明轉(zhuǎn)換符為顯式
using System;
class BooleanInt
{
private int i;
public int Int
{
get{return i;}
set{i = value;}
}
public BooleanInt(){}
public BooleanInt(int i)
{Int = i;}
public BooleanInt(BooleanInt bi)
{Int = bi.Int;}
public static explicit operator int(BooleanInt bi) //重載(int) 重載后(int)就能把BooleaInt類型的值顯式的轉(zhuǎn)換成int類型了。
{return (int)bi.Int;}
}
class test
{
public static void Main()
{
BooleanInt bi = new BooleanInt(8);
int a= (int)bi;
Console.WriteLine(a);
Console.Read();
}
}
http://blog.csdn.net/kendezhu/article/details/4915129
轉(zhuǎn)載于:https://blog.51cto.com/flydragon0815/674582
總結(jié)
以上是生活随笔為你收集整理的泛型与操作符重载杂谈的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序、进程、线程之间的区别
- 下一篇: A damn at han’s Wind