最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#中的引用類型以及特殊引用類型詳解

 更新時間:2022年07月31日 09:43:17   作者:Darren?Ji  
本文詳細(xì)講解了C#中的引用類型以及特殊引用類型,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

基本

哪些屬于引用類型

類(object,string),接口、數(shù)組、委托

引用類型分配在哪里

  • 引用類型變量位于線程棧。
  • 引用類型實例分配在托管堆上。
  • 當(dāng)引用類型實例的大小小于85000bytes,被分配在GC堆上,當(dāng)大于或等于85000bytes,被分配在LOH(Large Object Heap)上。

變量(Variable),對象(Object),實例(Instance)

變量:
變量分配在線程棧上。
變量可以是值類型,也可以是引用類型。
當(dāng)變量是引用類型時,包含了對對象的引用(內(nèi)存地址),也叫做"對象引用"。

對象:
對類、接口、委托和數(shù)組等的一個抽象描述。

實例:
在堆上創(chuàng)建的對象,稱為對象實例。

引用類型沒有new意味著什么?

Object a = null;
Console.WriteLine(a.ToString());
運行報錯"未將對象引用設(shè)置到對象實例"。
意思是,在線程棧上創(chuàng)建的變量a沒有指向到堆上的對象實例。

托管堆上的垃圾回收

GC會遍歷所有托管堆上的對象,按照一定的遞歸遍歷算法,對那些沒有被引用的不可訪問對象實施回收。

new的背后發(fā)生了什么

    class Program 
    { 
        static void Main(string[] args) 
        { 
            Person p; 
            p = new Person(20); 
        } 
    }

    public class Person 
    { 
        public int _age;

        public Person(int age) 
        { 
            _age = age; 
        }

        public Person() 
        { 
            
        } 
    }

另外,引用類型的值,比如這里的引用類型Person中的值_age也被分配在托管堆上。   

線程棧上的2個變量引用同一個對象實例的內(nèi)存地址

線程棧上的2個變量引用同一個對象實例的內(nèi)存地址,改變其中一個變量的值會影響到另外一個變量。

    class Program 
    { 
        static void Main(string[] args) 
        { 
            Person p1 = new Person(20); 
            Person p2 = p1; 
            Console.WriteLine("沒有改變時p2的年齡是:" + p2._age + "歲"); 
            p1._age = 18; 
            Console.WriteLine("改變p1的值,p2的年齡也被改變了,現(xiàn)在是:" + p2._age + "歲,真好,年輕了!"); 
            Console.ReadKey(); 
        } 
    }

    public class Person 
    { 
        public int _age;

        public Person(int age) 
        { 
            _age = age; 
        }

        public Person() 
        { 
            
        } 
    }

string類型是特殊的引用類型

特殊性體現(xiàn)在

從應(yīng)用角度體現(xiàn)了值類型語義,從內(nèi)存角度實現(xiàn)為引用類型存儲,位于托管堆。

什么是string

可以看作是char的集合char[]    

string創(chuàng)建與實例化

string str = "Hello";

以下錯誤
String str = new String("Hello");
因為System.String沒有提供此構(gòu)造函數(shù)

以下可以
Char[] cs = {'a', 'b','c'};
String strArr = new String(cs);
但很少使用這種方式。

字符串的恒定性Immutability

是指字符串一經(jīng)創(chuàng)建,就不可改變。
字符串一旦創(chuàng)建,在托管堆上分配一塊連續(xù)的內(nèi)存空間。

恒定性的好處:
對String對象的任意操作,不會改變原字符串。
操作字符串不會出現(xiàn)線程同步的問題。
成就了字符串駐留。

恒定性的不足:
因為恒定性,對字符串的任何操作,比如字符串比較,字符串鏈接,字符串格式化等都會創(chuàng)建新的字符串,這樣造成內(nèi)存與性能的雙重?fù)p耗。如下:

public static void Main() 
{ 
    string str = "This is a test about immuntablility of string type."; 
    Console.WriteLine(str.Inseert(0,"Hi").Substring(19).ToUpper()); 
    Console.WriteLine(str); 
}

由于Insert,Substring,ToUpper這些方法,都會創(chuàng)建出新的臨時字符串,而這些新的字符串不被其他代碼引用的時候,就會被垃圾回收,造成性能上的損失。

恒定性的前提,String為密封類:

public sealed class String:IComparable, ICloneable,IConvertible,IComparable<string>,IEnumerable<char>,IEnumerable,IEquatable<string>

字符串駐留String Interning

MSDN對于字符駐留的定義:公共語言運行庫通過維護(hù)一個哈希表(Hash Table)來存放字符串,該表成為拘留池,也叫駐留池。

字符串駐留彌補了恒定性的不足:
對于相同的字符串,CLR不會不會為其分配內(nèi)存空間,而是共享同一內(nèi)存。
CLR內(nèi)部維護(hù)了一個哈希表HashTable來管理其創(chuàng)建的大部分String對象。key是string本身,value是string對應(yīng)的內(nèi)存地址。

駐留的2個靜態(tài)方法:
public static string Intern(string str);
當(dāng)str位于作為key位于CLR的駐留池時,返回對str的引用,否則將str字符串添加到hash table中,作為key,并返回引用。

public static string IsInterned(string str);
當(dāng)str位于作為key位于CLR的駐留池時,返回對str的引用,否則返回null引用,也不添加到hash table中。

字符串駐留是進(jìn)程級的

可以跨應(yīng)用程序域AppDomain而存在,駐留池在CLR加載時創(chuàng)建,分配在System Domain中,被進(jìn)程所有AppDomain所共享,其生命周期不受GC控制。

例子1:

        static void Main(string[] args) 
        { 
            string strA = "ab"; 
            string strB = "ab"; 
            Console.WriteLine(ReferenceEquals(strA,strB)); 
            string strC = "a"; 
            string strD = strC + "b"; 
            Console.WriteLine(ReferenceEquals(strA, strD)); 
            strD = String.Intern(strD); 
            Console.WriteLine(ReferenceEquals(strA,strD)); 
            Console.ReadKey(); 
        }

返回:

true
false
true

分析:

  • strA與strB內(nèi)容相同,在hash table中的key相同,對應(yīng)了一樣的引用地址,所以返回true。
  • strD的內(nèi)容雖然與strA相同,但由于是動態(tài)生成的,不會把hash table中key為ab的引用地址賦值給strD,所以strA與strD引用地址不一樣,返回false。
  • strD = String.Intern(strD);手動對strD實施駐留,并發(fā)現(xiàn)hash table中已經(jīng)有了ab這個key,就把對應(yīng)的引用地址賦值給了strD,這樣,strA與strD引用地址相同,返回true。

例子2:

        static void Main(string[] args) 
        { 
            string s1 = "abc"; 
            string s2 = "ab"; 
            string s3 = s2 + "c"; 
            Console.WriteLine(string.IsInterned(s3) ?? "null"); 
            Console.WriteLine(ReferenceEquals(s1,s3)); 
            Console.ReadKey(); 
        }

返回:

abc
false   

分析:

  • string.IsInterned(s3)對s3進(jìn)行手動駐留,發(fā)現(xiàn)hash table中abc這個key,于是,就返回abc的引用地址。但并沒有把引用地址賦值給s3。
  • s1和s3的引用地址還是不一樣,返回false。

例子3:

        static void Main(string[] args) 
        { 
            string strA = "abcdef"; 
            string strC = "abc"; 
            string strD = strC + "def"; 
            Console.WriteLine(ReferenceEquals(strA,strD)); 
            string StrE = "abc" + "def"; 
            Console.WriteLine(ReferenceEquals(strA,StrE)); 
            Console.ReadKey(); 
        }

返回:

False,       
true

分析:

  • 因為strD = strC + "def"中strD的內(nèi)容雖然與strA想同,但因為是動態(tài)生成的,不會被添加到hash table中,所以引用地址不一樣,返回false。
  • "abc"+"def在IL中呈現(xiàn)為abcdef,不是動態(tài)生成的,并且發(fā)現(xiàn)hash table中已經(jīng)有了abcdef這個key,于是就把對應(yīng)的引用地址賦值給了strE,這樣strA和StrE就有了相同的引用地址,返回true。如圖:

例子4:

        static void Main(string[] args) 
        { 
            string s = "abc"; 
            //IsInterned()獲取字符串變量的引用 
            Console.WriteLine(string.IsInterned(s) ?? "null"); 
            Console.ReadKey(); 
        }

返回

"abc"。

分析:通過string s = "abc"使得hash table中有abc這個key,當(dāng)進(jìn)行string.IsInterned(s)手動駐留判斷的時候,發(fā)現(xiàn)有abc這個key,就把對應(yīng)的引用地址返回。

例子5:

    class Program 
    { 
        static void Main(string[] args) 
        { 
            string s = "ab"; 
            s += "c"; 
            //IsInterned()獲取字符串變量的引用 
            Console.WriteLine(string.IsInterned(s) ?? "null"); 
            Console.ReadKey(); 
        } 
    }

返回

null

分析:通過string s = "ab";使得hash table中有了ab這個key,s += "c"是動態(tài)拼接,不會把abc放到hashtable中,所以當(dāng)通過string.IsInterned(s)手動駐留判斷的時候,發(fā)現(xiàn)沒有abc這個key,就返回null。

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接

相關(guān)文章

  • c#唯一值渲染實例代碼

    c#唯一值渲染實例代碼

    這篇文章主要介紹了c#唯一值渲染實例代碼,有需要的朋友可以參考一下
    2013-12-12
  • C#使用TensorFlow.NET訓(xùn)練自己的數(shù)據(jù)集的方法

    C#使用TensorFlow.NET訓(xùn)練自己的數(shù)據(jù)集的方法

    這篇文章主要介紹了C#使用TensorFlow.NET訓(xùn)練自己的數(shù)據(jù)集的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • 淺談C#索引器

    淺談C#索引器

    這篇文章主要簡單介紹C#索引器,索引器使你可從語法上方便地創(chuàng)建類、結(jié)構(gòu)或接口,以便客戶端應(yīng)用程序可以像訪問數(shù)組一樣訪問它們。編譯器將生成一個 Item 屬性和適當(dāng)?shù)脑L問器方法,在主要目標(biāo)是封裝內(nèi)部集合或數(shù)組的類型中,常常要實現(xiàn)索引器,下面我們一起來看看具體內(nèi)容吧
    2021-11-11
  • 在Winform動態(tài)啟動、控制臺命令行的方法

    在Winform動態(tài)啟動、控制臺命令行的方法

    winForm 程序輸出類型為 windows 程序(不是命令行程序)在運行時想輸入一些信息編譯開發(fā)調(diào)試,如何實現(xiàn)這一功能
    2013-02-02
  • C#獲取真實IP地址(IP轉(zhuǎn)為長整形、判斷是否內(nèi)網(wǎng)IP的方法)

    C#獲取真實IP地址(IP轉(zhuǎn)為長整形、判斷是否內(nèi)網(wǎng)IP的方法)

    這篇文章主要介紹了C#獲取真實IP地址的實現(xiàn)代碼,包含把IP轉(zhuǎn)為長整形、判斷是否是私網(wǎng)、內(nèi)網(wǎng)IP的方法,需要的朋友可以參考下
    2014-08-08
  • C#實現(xiàn)動態(tài)生成表格的方法

    C#實現(xiàn)動態(tài)生成表格的方法

    這篇文章主要介紹了C#實現(xiàn)動態(tài)生成表格的方法,是C#程序設(shè)計中非常實用的技巧,需要的朋友可以參考下
    2014-09-09
  • C#實現(xiàn)高性能異步文件下載器詳解

    C#實現(xiàn)高性能異步文件下載器詳解

    異步文件下載器用處很大,當(dāng)我們需要實現(xiàn)大文件下載,多任務(wù)并行下載等都可以用的上,下面小編就來和大家聊聊如何使用C#實現(xiàn)高性能異步文件下載器吧
    2025-03-03
  • C#自定義事件及用法實例

    C#自定義事件及用法實例

    這篇文章主要介紹了C#自定義事件及用法,實例分析了C#中自定義事件的定義與使用技巧,需要的朋友可以參考下
    2015-05-05
  • DevExpress之ChartControl實現(xiàn)餅狀圖百分比演示實例

    DevExpress之ChartControl實現(xiàn)餅狀圖百分比演示實例

    這篇文章主要介紹了DevExpress之ChartControl實現(xiàn)餅狀圖百分比演示的方法,實例講述了窗體與圖形繪制函數(shù)的用法,需要的朋友可以參考下
    2014-10-10
  • 詳解C# WebApi 接口測試工具:WebApiTestClient

    詳解C# WebApi 接口測試工具:WebApiTestClient

    這篇文章主要介紹了詳解C# WebApi 接口測試工具:WebApiTestClient,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07

最新評論

昌图县| 个旧市| 新民市| 化德县| 盐津县| 沂南县| 台中市| 宁远县| 垣曲县| 镇安县| 河北省| 连山| 灵石县| 封丘县| 前郭尔| 微博| 铜鼓县| 柘城县| 成武县| 丰台区| 浦北县| 淅川县| 东光县| 南木林县| 千阳县| 凤凰县| 福鼎市| 山西省| 郴州市| 从江县| 新野县| 巴中市| 靖西县| 吉首市| 乐昌市| 临沧市| 赣州市| 江永县| 鲁山县| 遵化市| 临沂市|