<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      C#方法

      C#方法

      1:實例構造器和類

      2:實例構造器和結構

      3:類型構造器

      4:操作符重載方法

      5:轉換操作符方法

      6:擴展方法

      7:部分方法

       

      這篇博客的內容基本上是CLR via C#中第八章 “方法”的大致內容,如果我說得不對,歡迎大家搬磚頭

       

      1:實例構造器和類

      構造器是允許將類型的實例初始化為良好狀態的一種特殊方法,創建一個引用類型的實例時,先為實例的數據字段分配內存,然后初始化對象的附加字段(類型對象指針和同步索引),最后調用構造函數來設置對象的初始狀態。構造函數不能被繼承,所以不能被virtual、new、override、sealed和abstract修飾,若沒有顯示定義任何構造函數,編譯器將定義一個無參的public構造函數,但若是抽象類,編譯器將定義一個無參的protected的構造函數

       

      創建一個類的實例并不一定非要調用構造函數。

      1:使用ObjectMemberwiseClone()方法。他的作用就是創建當前 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:部分方法

      你懂的


        作者:陳太漢

        博客:http://www.rzrgm.cn/hlxs/

       

       

      posted @ 2011-12-10 16:43  古文觀芷  閱讀(6633)  評論(5)    收藏  舉報
      主站蜘蛛池模板: 精品福利一区二区三区免费视频| 一本大道久久香蕉成人网| 韩国三级网一区二区三区| 亚洲中文在线精品国产| 武冈市| 四虎库影成人在线播放| 国产亚洲精品aaaa片app| 粗大挺进朋友人妻淑娟| 肉大榛一进一出免费视频| 成av人电影在线观看| 麻豆国产成人AV在线播放| 成人无码特黄特黄AV片在线| 久久视频在线视频| av偷拍亚洲一区二区三区| 99久久国产福利自产拍| 亚洲精品97久久中文字幕无码| 嘉祥县| 亲子乱aⅴ一区二区三区| 亚洲国产超清无码专区| 尤物yw193无码点击进入| 天天躁夜夜躁天干天干2020| 女同性恋一区二区三区视频| 日韩 欧美 亚洲 一区二区| 欧美丰满熟妇bbbbbb| 欧美人与zoxxxx另类| 亚洲欧美人成电影在线观看| 一区二区乱子伦在线播放| 亚洲久久色成人一二三区| 久久精品国产国产精品四凭| 免费人成视频在线| 777奇米四色成人影视色区| 国产精品va在线观看h| 国产精品女生自拍第一区| 国产成人一区二区三区在线| 国产精品亚洲二区在线播放| 亚洲永久一区二区三区在线| 少妇午夜啪爽嗷嗷叫视频| 绍兴市| 欧美牲交a欧美牲交aⅴ一| 青青青青久久精品国产| 仪陇县|