C#方法的總結詳解

來源:互聯網
上載者:User

C#方法
1:執行個體構造器和類
2:執行個體構造器和結構
3:類型構造器
4:操作符重載方法
5:轉換操作符方法
6:擴充方法
7:部分方法
1:執行個體構造器和類
構造器是允許將類型的執行個體初始化為良好狀態的一種特殊方法,建立一個參考型別的執行個體時,先為執行個體的資料欄位分配記憶體,然後初始化對象的附加欄位(類型對象指標和同步索引),最後調用建構函式來設定對象的初始狀態。建構函式不能被繼承,所以不能被virtual、new、override、sealed和abstract修飾,若沒有顯示定義任何建構函式,編譯器將定義一個無參的public建構函式,但若是抽象類別,編譯器將定義一個無參的protected的建構函式
建立一個類的執行個體並不一定非要調用建構函式。
1:使用Object的MemberwiseClone()方法。他的作用就是建立當前 System.Object 的淺表副本,內部工作機制是分配記憶體,初始化對象的附加欄位(類型對象指標和同步索引),然後將來源物件的位元組資料複製到新對象中。從下面的代碼可以看出MemberwiseClone()實現了對象複製,而不是簡單的對象引用。 複製代碼 代碼如下:class Program
{
public int X;
static void Main(string[] args)
{
Program p = new Program();
p.X = 1;
Program q = (Program)p.MemberwiseClone();
Program z = p;
p.X = 2;
Console.WriteLine("p.X=" + p.X);//輸出:p.X=2
Console.WriteLine("q.X=" + q.X);//輸出:q.X=1
Console.WriteLine("z.X=" + z.X);//輸出:z.X=2
Console.Read();
}
}

2:還原序列化。在網路編程的時候,經常將一個對象序列化成二進位,然後傳輸出去,接收端還原序列化成原來的對象,還原序列化使用的是類
System.Runtime.Serialization.FormatterServices的方法public static object GetUninitializedObject(Type type)或
public static object GetSafeUninitializedObject(Type type)分配記憶體,而在這兩個方法內部沒有調用要被還原序列化對象的建構函式。
欄位的初始化代碼會被編譯器自動添加到相應的建構函式中,非靜態欄位的初始化代碼會自動加到執行個體建構函式中,靜態欄位的初始化代碼則添加到靜態建構函式中,如果你的代碼中有多個欄位被初始化,還有多個建構函式的話,初始化代碼在每個建構函式中都會有一份,這無疑會讓你的組建檔案(如DLL,EXE檔案)變大。
證明這一點的代碼如下:複製代碼 代碼如下:public class SomeType
{
public int x=1,y=2,z=3;
public SomeType() { }
public SomeType(int x, int y)
{
this.x = x;
this.y = y;
}
public SomeType(int x)
{
this.x = x;
}
}
//經過IL反編譯,方法SomeType(int x, int y)代碼如下
.method public hidebysig specialname rtspecialname
instance void .ctor(int32 x,
int32 y) cil managed
{
// 代碼大小 45 (0x2d)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: stfld int32 MyTest.SomeType::x
IL_0007: ldarg.0
IL_0008: ldc.i4.2
IL_0009: stfld int32 MyTest.SomeType::y
IL_000e: ldarg.0
IL_000f: ldc.i4.3
IL_0010: stfld int32 MyTest.SomeType::z
IL_0015: ldarg.0
IL_0016: call instance void [mscorlib]System.Object::.ctor()
IL_001b: nop
IL_001c: nop
IL_001d: ldarg.0
IL_001e: ldarg.1
IL_001f: stfld int32 MyTest.SomeType::x
IL_0024: ldarg.0
IL_0025: ldarg.2
IL_0026: stfld int32 MyTest.SomeType::y
IL_002b: nop
IL_002c: ret
} // end of method SomeType::.ctor

先執行了初始化代碼,其他建構函式都包含了初始化代碼,然後在執行建構函式中的賦值代碼,要解決這個代碼膨脹問題,方法很簡單,把初始化代碼寫在無參建構函式中,讓其他建構函式調用。
2:執行個體構造器和結構
實值型別的工作方式與參考型別截然不同,實值型別其實並不需要定義建構函式,地球人根本阻止不了實值型別執行個體化,編譯器根本不會生產預設無參建構函式,如果你顯示聲明無參建構函式,編譯根本通過不了,報錯“結構不能包含顯式的無參數建構函式”。由於實值型別存在棧中,根本不需要對堆中的資料進行引用,所以我們可以在定義的時候就直接賦值,(int i=0;string s=”a”;Point p;p.X=2;)他根本不需要new,new當然是可以的,調用建構函式會初始化所有的欄位成相應類型的預設值,執行個體如下:複製代碼 代碼如下:public struct Point
{
public int x, y;
//public Point() { }//錯:結構不能包含顯式的無參數建構函式
//public int z = 4;//錯:結構中不能有執行個體欄位初始值設定項
//public Point(int x) //在控制返回調用方之前,欄位“Point.y”必須被完全賦值,要解決這個問題就手動給y加一個預設值吧,
//你也可以加this=new Point();將所有的欄位的值初始化為0或null
//{
// this.x = x;
//}
public void Test()
{
Point p;
p.x = 1;
p.y = 2;
Console.WriteLine(p.x+","+p.y);//輸出1,2
}
}

結構的特點:
1:不能顯示定義無參建構函式
2:不能在定義欄位的時候初始化
3:聲明有參建構函式的時候,要初始化所有的欄位
3:類型構造器
執行個體構造器就是靜態建構函式,他的作用是設定類型的初始化狀態,靜態建構函式只能有一個,且是無參的,不能有存取修飾詞修飾,預設就是private,由編譯器調用執行。執行個體如下:複製代碼 代碼如下:public class SomeType
{
public static int x = 520;
static SomeType()
{
x = 112;
}
}

//用.NET reflector查看源碼,如下
public class SomeType
{
public static int x ;
static SomeType()
{
x = 520;
x = 0x70;
}
public SomeType() { }
}

在定義靜態欄位並初始化,編譯器會自動產生一個類型構造器(靜態建構函式),並將靜態欄位的初始化代碼插在類型構造器的前面,從上面的代碼可以看出,定義時初始化和在類型構造器中初始化只需要一個即可,還有112的16進位為0x70,所以在代碼中看到16進位也不用大驚小怪,根本不涉及效能問題,若定義了靜態欄位,但沒有初始化任何一個,編譯器是不會組建類型構造器的。但是靜態欄位還是會被初始化,其實不管是靜態還是非靜態欄位都是會被編譯器自動初始化的,int類型的初始化為0;bool:False;string:null,這就是為什麼你在執行個體化實體的時候,有些欄位你沒有初始化,卻不會報錯,而且你知道沒有初始化的字串的值就是null,也就是說編譯器會幫你初始化你沒有初始化的欄位,然而在方法中定義的局部變數是需要自己初始化的,如果你沒有初始化,會報一個錯誤“使用了未賦值的局部變數X”。
4:操作符重載方法
要想實現操作符重載,只需要保證以下兩點,其他的話都是浮云:
1:操作符重載方法必須是public和static方法
2:操作符重載方法至少有一個參數的類型與當前定義這個方法的類型相同。之所以是要這個條件是為了使編譯器在合理的時間內找到要綁定的操作方法,執行個體如下複製代碼 代碼如下:public class Complex
{
public int data;
public Complex(int data)
{
this.data = data;
}
public static Complex operator +(Complex c1, Complex c2)
{
return new Complex(c1.data+c2.data);
}
public void Test()
{
Complex c1 = new Complex(1);
Complex c2 = new Complex(2);
Complex c3 = c1 + c2;
Console.WriteLine(c3.data);//輸出3
}
}

5:轉換操作符方法
要實現轉換操作符方法,條件和操作符重載方法的條件是一樣的,執行個體如下:複製代碼 代碼如下:public class Rational
{
public Rational(int data)
{
this.data = data;
}
public Rational(char data)
{
this.data = (int)data;
}
//隱式類型轉換:int->Rational
public static implicit operator Rational(int data)
{
return new Rational(data);
}
//隱式類型轉換:char->Rational
public static implicit operator Rational(char data)
{
return new Rational(data);
}
//顯示類型轉換 Rational->int
public static explicit operator int(Rational val)
{
return val.data;
}
//顯示類型轉換 Rational->char
public static explicit operator char(Rational val)
{
return Convert.ToChar(val.data);
}
public void Test()
{
Rational r1 = 1;//將int類型隱式轉換成Rational
Rational r2 = '2';//將char類型隱式轉換成Rational
int i = (int)r1;//將Rational類型顯示轉換成int
char c = (char)r2;//將Rational類型顯示轉換成char
Console.WriteLine("i=" + i);//輸出:i=1
Console.WriteLine("c=" + c);//輸出:c=2
}

int data;
}

隱式和顯示類型轉換的實現原理就這麼簡單,在C++中隱式類型轉換根本不需要你寫代碼,只要有相應的public建構函式就可以了,如int轉換成Rational,只需要有建構函式public Rational(int data)就可以了,如Rational r=1;編譯器會盡一切努力尋找將int類型轉換成Rational的方法,當它發現這個建構函式,他說都不說就幫你進行轉換了,就因為這樣有時候非常坑爹,你一個int類型無緣無故的就變成Rational了,而你卻根本不知道怎麼回事,有時候為瞭解決這個問題,還得自己定義一個類(Uint)來封裝int,然後建構函式改成Rational(Uint data),C#就沒有這個問題,當然你要想實現隱式類型轉換就自己寫代碼吧。
6:擴充方法
實現擴充方法的條件:
1:定義擴充方法的類必須是非泛型靜態類
2:這個類必須有自己的範圍,即不能是內部類
3:方法必須是public和static
4:方法的第一個參數必須用this修飾,第一個參數就是你要擴充的類型,執行個體如下:
複製代碼 代碼如下:public static class StringExtensions
{
public static int ToInt(this string s)
{
return Convert.ToInt32(s);
}
public void Test()
{
string s = "2";
Console.WriteLine(s.ToInt());
}
}

7:部分方法
你懂的

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.