1均函、C#語言中的類型
類型被分為兩種:值類型(整數(shù),bool struct char 小數(shù))和引用類型(string 數(shù)組 自定義的類菱涤,內(nèi)置的類)苞也。
值類型與引用類型的關(guān)系
類別 | 具體 | |
---|---|---|
值類型 | 基本數(shù)據(jù)類型 | 整型:int |
值類型 | 基本數(shù)據(jù)類型 | 長整型:long |
值類型 | 基本數(shù)據(jù)類型 | 浮點型:float |
值類型 | 基本數(shù)據(jù)類型 | 字符型:char |
值類型 | 基本數(shù)據(jù)類型 | 布爾型:bool |
值類型 | 結(jié)構(gòu)類型 | 結(jié)構(gòu):struct |
值類型 | 枚舉類型 | 枚舉:enum |
引用類型 | 類 | 基類:System.Object |
引用類型 | 類 | 字符串:string |
引用類型 | 類 | 自定義類:class |
引用類型 | 接口 | 接口:interface |
引用類型 | 數(shù)組 | 數(shù)組:int[],list<T>[]粘秆,string[] |
- 值類型
只需要一段單獨的內(nèi)存如迟,用于存儲實際的數(shù)據(jù),(單獨定義的時候放在棧中) - 引用類型
需要兩段內(nèi)存:第一段存儲實際的數(shù)據(jù)翻擒,它總是位于堆中氓涣,第二段是一個引用,指向數(shù)據(jù)在堆中的存放位置
當(dāng)我們使用引用類型賦值的時候陋气,其實是賦值的引用類型的引用劳吠。
如果數(shù)組是一個值類型的數(shù)組,那么數(shù)組中直接存儲值巩趁,如果是一個引用類型的數(shù)組(數(shù)組中存儲的是引用類型)痒玩,那么數(shù)組中存儲的是引用(內(nèi)存地址)。
分析下面的變量在內(nèi)存中的表示方式
static void Test1()
{
int i = 34;
int j = 34;
int temp = 334;
char c = 'a';
bool b = true;
}
static void Test2()
{
int i = 34;
int j = 234;
string name = "zhangsan";
}
static void Test3()
{
string name = "zhangsan";
string name2 = "lisi";
name = name2;
name = "wangwu";
Console.WriteLine(name+":"+name2);
}
- 思考:
static void Main()
{
int number = 10;
add(number);
Console.WriteLine(number);
Console.ReadLine();
}
static void add(int number)
{
number = number+number;
Console.WriteLine(number);
}
2议慰、兩個方法修飾關(guān)鍵字
- ref用途
ref用來修飾方法的參數(shù)蠢古,被ref修飾的參數(shù),在調(diào)用的時候别凹,會傳遞過來的是一個引用草讶。當(dāng)在方法中修改參數(shù)時,那么調(diào)用方傳遞過來的那個變量的值也會被改變炉菲。在將要調(diào)用的方法的參數(shù)中堕战,如果有ref修飾的參數(shù),那么該參數(shù)需要在傳遞之前初始化拍霜。
它可以將值類型強(qiáng)制改為引用類型
看下面的例子來理解:
static void Main()
{
int x = 10;
TestRef(ref x); //傳的參數(shù)是x所在的內(nèi)存地址
Console.WriteLine(x); // 20
}
static void TestRef( ref int number1) //這里是指向值為10的內(nèi)存地址
{
Console.WriteLine("TestRef輸出"+ number1); //10
number1 += number1;
Console.WriteLine("TestRef輸出" + number1);// 20
}
- out用途
out也是用來修飾方法的參數(shù)嘱丢,跟ref很類似,被out修飾的參數(shù)祠饺,在調(diào)用的時候越驻,會傳遞過來的是一個引用。當(dāng)在方法中修改參數(shù)時,那么調(diào)用方傳遞過來的那個變量的值也會被改變缀旁。在將要調(diào)用的方法的參數(shù)中记劈,如果有out修飾的參數(shù),那么該參數(shù)可以不需要在傳遞之前初始化诵棵。(賦值沒有意義)
看下面的例子
static void Main()
{
int y;
TestOut(out y);
Console.WriteLine(y); //30
Console.ReadLine();
}
static void TestOut(out int number1)
{
number1 = 30;
Console.WriteLine("TestOut輸出" + number1); // 30
}
- ref和out的不同點:
ref修飾的參數(shù)在傳遞之前必須要初始化抠蚣。
ref應(yīng)用場景內(nèi)部對外部的值進(jìn)行改變,
out修飾的參數(shù)在傳遞之前可以不初始化履澳。
out則是內(nèi)部為外部變量賦值嘶窄,一般用在函數(shù)有多個返回值的場所
3、值類型與引用類型的傳遞
- 方法的值傳遞
public static void GetValue(int number)
{
number = 40;
}
static void Main(string[] args)
{
int number = 20;
GetValue(number);
Debug.Log(number);
}
- 特殊引用類型的值傳遞
public static void GetStr(string str)
{
str = "Sunyin";
}
static void Main(string[] args)
{
string str = "leichao";
GetStr(str);
Console.WriteLine(str); // 打印leichao
}
- 地址引用與值引用案例
string temp1 = new string(new char[] { 'L', 'c' });
string temp2 = new string(new char[] { 'L', 'c' });
Debug.Log(temp1 == temp2);
Debug.Log(temp1.Equals(temp2));
// 輸出結(jié)果是true true
object temp3 = temp1;
object temp4 = temp2;
Debug.Log( "4與3比較"+(temp4 == temp3));
Debug.Log(temp3.Equals(temp4));
// 輸出結(jié)果false true
- 引用傳遞
public static void GetStr( ref string str)
{
str = "Sunyin";
}
static void Main(string[] args)
{
string str = "leichao";
GetStr(ref str);
Console.WriteLine(str); // 結(jié)果就變成Sunyin了
}
4距贷、拆箱與裝箱
- 裝箱
裝箱是將值類型轉(zhuǎn)換為object
類型或由此值類型實現(xiàn)的任何接口類型的過程
int i = 123;
object o = i;
image.png
- 拆箱
從object
類型到值類型或從接口類型到實現(xiàn)該接口的值類型的顯式轉(zhuǎn)換
int i = 123; // a value type
object o = i; // boxing
int j = (int)o; // unboxing
拆箱
拆箱
5柄冲、總結(jié)
- 1、基本數(shù)據(jù)類型比較
==和Equals都比較兩個值是否相等忠蝗。相等為true 否則為false现横; - 2、引用對象比較
==和Equals都是比較棧內(nèi)存中的地址是否相等 阁最。相等為true 否則為false戒祠; - 3、注意
1速种、string是一個特殊的引用類型姜盈。對于兩個字符串的比較,不管是 == 和 Equals 這兩者比較的都是字符串是否相同配阵;
2馏颂、當(dāng)你創(chuàng)建兩個string對象時,內(nèi)存中的地址是不相同的棋傍,你可以賦相同的值救拉。
所以字符串的內(nèi)容相同。引用地址不一定相同瘫拣,(相同內(nèi)容的對象地址不一定相同)亿絮,但反過來卻是肯定的;
3麸拄、基本數(shù)據(jù)類型比較(string 除外) == 和 Equals 兩者都是比較值派昧; - 4、判斷兩個對象是否相同要用:object.ReferenceEquals();