亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

C#中的引用類型以及特殊引用類型怎么使用

發布時間:2022-08-01 11:13:01 來源:億速云 閱讀:126 作者:iii 欄目:開發技術

這篇“C#中的引用類型以及特殊引用類型怎么使用”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“C#中的引用類型以及特殊引用類型怎么使用”文章吧。

基本

哪些屬于引用類型

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

引用類型分配在哪里

  • 引用類型變量位于線程棧。

  • 引用類型實例分配在托管堆上。

  • 當引用類型實例的大小小于85000bytes,被分配在GC堆上,當大于或等于85000bytes,被分配在LOH(Large Object Heap)上。

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

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

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

實例:
在堆上創建的對象,稱為對象實例。

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

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

托管堆上的垃圾回收

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

new的背后發生了什么

    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也被分配在托管堆上。   

C#中的引用類型以及特殊引用類型怎么使用

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

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

    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的年齡也被改變了,現在是:" + p2._age + "歲,真好,年輕了!"); 
            Console.ReadKey(); 
        } 
    }

    public class Person 
    { 
        public int _age;

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

        public Person() 
        { 
            
        } 
    }

C#中的引用類型以及特殊引用類型怎么使用

string類型是特殊的引用類型

特殊性體現在

從應用角度體現了值類型語義,從內存角度實現為引用類型存儲,位于托管堆。

什么是string

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

string創建與實例化

string str = "Hello";

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

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

字符串的恒定性Immutability

是指字符串一經創建,就不可改變。
字符串一旦創建,在托管堆上分配一塊連續的內存空間。

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

恒定性的不足:
因為恒定性,對字符串的任何操作,比如字符串比較,字符串鏈接,字符串格式化等都會創建新的字符串,這樣造成內存與性能的雙重損耗。如下:

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這些方法,都會創建出新的臨時字符串,而這些新的字符串不被其他代碼引用的時候,就會被垃圾回收,造成性能上的損失。

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

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

字符串駐留String Interning

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

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

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

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

字符串駐留是進程級的

可以跨應用程序域AppDomain而存在,駐留池在CLR加載時創建,分配在System Domain中,被進程所有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內容相同,在hash table中的key相同,對應了一樣的引用地址,所以返回true。

  • strD的內容雖然與strA相同,但由于是動態生成的,不會把hash table中key為ab的引用地址賦值給strD,所以strA與strD引用地址不一樣,返回false。

  • strD = String.Intern(strD);手動對strD實施駐留,并發現hash table中已經有了ab這個key,就把對應的引用地址賦值給了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進行手動駐留,發現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的內容雖然與strA想同,但因為是動態生成的,不會被添加到hash table中,所以引用地址不一樣,返回false。

  • "abc"+"def在IL中呈現為abcdef,不是動態生成的,并且發現hash table中已經有了abcdef這個key,于是就把對應的引用地址賦值給了strE,這樣strA和StrE就有了相同的引用地址,返回true。如圖:

C#中的引用類型以及特殊引用類型怎么使用

例子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,當進行string.IsInterned(s)手動駐留判斷的時候,發現有abc這個key,就把對應的引用地址返回。

例子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"是動態拼接,不會把abc放到hashtable中,所以當通過string.IsInterned(s)手動駐留判斷的時候,發現沒有abc這個key,就返回null。

以上就是關于“C#中的引用類型以及特殊引用類型怎么使用”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

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

AI

安仁县| 农安县| 东源县| 通州市| 星座| 胶州市| 丰县| 克拉玛依市| 民勤县| 青神县| 西平县| 辽源市| 嘉义市| 宝山区| 宾川县| 嘉兴市| 普宁市| 屯门区| 正定县| 洪泽县| 宿州市| 宁乡县| 南丹县| 安龙县| 拉孜县| 德格县| 勐海县| 黔西县| 界首市| 北辰区| 罗甸县| 仙居县| 盐池县| 寻乌县| 霍城县| 水富县| 呼伦贝尔市| 临猗县| 陆丰市| 河北区| 长丰县|