溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

構造器和引用類型是什么

發布時間:2020-07-14 16:59:33 來源:億速云 閱讀:167 作者:Leah 欄目:編程語言

今天就跟大家聊聊有關構造器和引用類型是什么,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

引用類型
構造器是將類型的實例初始化為良好狀態的特殊方法,創建引用類型的實例時,首先為實例的數據字段分配內存,然后初始化對象的附加字段(類型對象指針和同步塊索引),最后調用類型的實例構造器來設置對象的初始化狀態。
構造引用類型對象時,在電泳類型的實例構造器之前,為對象分配的內存總是先被歸0,沒有被構造器顯示重寫的所有字段都保證獲得0或null值。
和其他方法不同,實力構造器永遠不能被繼承,也就是說,類只有類自己定義的還順利構造器。由于永遠不能繼承實例構造器,所以實例構造器不能使用以下修飾符:Virtual,new,override,sealed和abstract。如果類沒有顯示定義任何構造器,C#編譯器將默認一個默認無參構造器,在她的實現中,只是簡單的調用了基類的無參構造函數。
如果類的修飾符為abstract,那么編譯器生成的默認構造器的可訪問性就為product;否則,構造器會被賦予public可訪問屬性。如果基類沒有提供無參構造器,那么派生類必須顯示調用一個基類構造器,否則編譯器會報錯。如果類的修飾符為static(sealed和abstract),編譯器根本不會再類的定義中生成默認的構造器。
一個類型可以定義多個實例構造器。每個構造器都必須有不同的簽名,而且每個都可以有不同的可訪問屬性。為了使代碼“可驗證”,類的實力構造器在訪問從基類繼承的任何字段前,必須先調用基類的構造器。如果派生類的構造器沒有顯示調用一個基類構造器,C#編譯器會自動生成對默認的基類構造器的調用。最終,System.Object的公共無參構造器會得到調用。該構造器什么都不做,會直接返回,由于System.Object沒有實例數據字段,所以它的構造器無事可做。
極少數情況下可以在不調用實例構造器的前提下創建類型實例。一個典型的例子就是Object的MemberwiseClone方法。該方法的作用是分配內存,初始化對象的附加字段,然后將源對象的自己數據復制到新對象中。另外,用運行時序列化器(runtime seriallizer)反序列化對象時,同程也不需要調用構造器。反序列化使用System.Runtime.Serialization.FormatterServices類型的GetUninitalizedObject或者GetSafeUninitailizedObject方法為對象分配內存,期間不會調用一個構造器。
提示:
不要再構造器中調用虛方法。原因是假如被實例化的類型重寫了虛方法,就會執行派生類型對虛方法的實現,但是在這個時候,尚未完成對繼承層次結構中所有字段的初始化(被實例化的類型的構造器還沒有運行)。所以,調用虛方法會導致無法預測的行為。歸根到底,這是由于調用虛方法時,直到運行時之前都不會選擇執行該方法的實際類型。
值類型(struct)構造器
值類型(struct)構造器的工作方式與引用類型(class)的構造器截然不同。CLR總是允許創建值類型的實例,并且沒有辦法阻止值類型的實例化。所以,值類型其實并不需要定義構造器,C#編譯器根本不會為值類型內聯默認無參構造器。來看下面代碼:
internal struct Point {
public int m_x, m_y;
}
internal sealed class Reactangel
{
public Point m_TopLeft, m_bottomRight;
}
為了構造一個Rectangle,必須使用new操作符,而且必須指定構造器。在這個例子中,調用的是C#編譯器自動生成的默認構造器。為Reatangle分配內存,內存中包含Point值類型的兩個實例??紤]到性能,CLR不會為包含在引用類型中的每個值類型字段都主動調用構造器,但是,如前所述,值類型的字段都會被初始化為0或null。
CLR確實允許為值類型定義構造器,但是必須顯示調用才會執行。
internal struct Point {
public int m_x, m_y;
public Point(int x, int y)
{
m_x = x;
m_y = y;
}
}
internal sealed class Reactangel
{
public Point m_TopLeft, m_bottomRight;
public Reactangel()
{
this.m_TopLeft = new Point(1,2);
this.m_bottomRight = new Point(100,200);
}
}
值類型的實例構造器只有顯示調用才會執行。因此,如果Rectangle的構造器沒有使用new操作符來調用Point的構造器,從而初始化Reatangle的m_TopLeft和m_bottomRight字段,那么兩個point字段中的m_x和m_y字段都將為0.
將上面代碼改寫:
internal struct Point {
public int m_x, m_y;
public Point()
{
m_x = 5;
m_y = 6;
}
}
internal sealed class Reactangel
{
public Point m_TopLeft, m_bottomRight;
public Reactangel()
{
}
}
現在,構造新的Rectangle類時,兩個Point字段中的m_x和m_y字段會被初始化多少,是0還是5?
可能你會覺得C#編譯器會子啊Reactangel的構造器中生成代碼,為Reactangel的兩個字段自動調用Point的默認無參構造器。但是,為了增強應用程序的運行時性能,C#編譯器不會自動生成這樣的代碼。實際上,即便值類型提供了無參構造器,許多編譯器也永遠不會生成代碼來調用它,為了執行值類型無參構造器,開發人員必須增加顯示調用值類型構造器的代碼。但是會由于這個原因Point‘的兩個字段被初始化為0嗎?結果是:
構造器和引用類型是什么
C#編譯器故意不允許值類型定義無參構造器,目的是防止開發人員對這種構造器在什么時候調用產生迷惑。由于不能定義無參構造器,所以編譯器永遠不會生成自動調用它的代碼,沒有無參構造器,值類型的字段總是被初始化為0或null。
類型構造器:
也稱為靜態構造器,類構造器或者類型初初始化器。類型構造器可應用與引用類型和值類型。實例構造器的作用是設置類型的實例的初始狀態。對應的,類型構造器的作用是設置類型的初始狀態。類型默認沒有定義類型構造器,如果定義,也只能有一個。此外,類型構造器永遠沒有參數。
internal sealed class SomeRefType {
static SomeRefType()
{
//首次訪問時,執行這里的代碼
}
}
internal struct SomeValType
{
static SomeValType()
{
//首次訪問時,執行這里的代碼
}
}
可以看出,定義類型構造器類似于定義無參實例構造器,區別在于必須標記為static。此外,類型構造器總是私有的。之所以私有,是為了防止任何開發人員寫代碼調用它,對他的調用總是有CLR負責。
提示:
雖然能在值類型中定義類型構造器,但永遠不要真的那么做,因為CLR有時不會調用值類型的靜態構造器:例如
internal struct SomeValType
{
static SomeValType()
{
Console.WriteLine("這句話永遠不會顯示");
}
public int m_x;
}
class Program
{
static void Main(string[] args)
{
SomeValType[] a = new SomeValType[10];
a[0].m_x = 123;
Console.WriteLine(a[0].m_x);
Console.ReadKey();
}
}
類型構造器的代碼只能訪問類型的靜態字段,并且他的非常規用途就是初始化這些字段。

看完上述內容,你們對構造器和引用類型是什么有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女