其他 1 命名空間 命名空間用來組織和重用代碼的,命名空間就像一個工具包,類就像工具。 1.1 使用 namespace MyGame { class GameObject { } } namespace MyGame//命名空間可以分開寫 { class Player : GameObject { ...
其他
1 命名空間
命名空間用來組織和重用代碼的,命名空間就像一個工具包,類就像工具。
1.1 使用
namespace MyGame
{
class GameObject
{
}
}
namespace MyGame//命名空間可以分開寫
{
class Player : GameObject
{
}
}
1.2 不同命名空間中相互使用
使用 using 命名空間名 或 命名空間名.內容 來使用所需命名空間的內容。
1.3 不同命名空間中允許有同名類
此時要使用同名類,必須指明出處的使用方法:命名空間名.類名
namespace MyGame2
{
class GameObject//不同命名空間的同名類
{
}
}
1.4 命名空間可以包裹命名空間
表示工具包裡面的小包,若要使用小包,必須using到小包,如:using MyGame.UI,只using MyGame是無法使用UI的。
namespace MyGame
{
namespace UI
{
class Image
{
}
}
namespace Game
{
class Image
{
}
}
}
//Main
GameObject g = new GameObject();
MyGame.UI.Image i = new MyGame.UI.Image();
1.5 關於修飾類的訪問修飾符
- public 公有類,命名空間中的類預設為public
- internal 內部類,只能在該工程的程式集中使用
- abstract 抽象類
- sealed 密封類
- partial 分部類
2 object 中的方法
2.1 靜態方法
Equals:判斷兩個對象是否相等,返回true或false
最終的判斷權由左側對象決定,不管是值類型還是引用類型都按照左側對象的規則來比較
ReferenceEquals:判斷兩個對象是否是相同的引用,用來比較引用類型的對象
值類型對象的返回值始終是false
class Test
{
}
//Main
Console.WriteLine(Object.Equals(1, 1));//值類型
Test t1 = new Test();
Test t2 = new Test();
Test t3 = t1;
Console.WriteLine(Object.Equals(t1,t2));//引用類型
Console.WriteLine(Object.Equals(t1,t3));
Console.WriteLine(ReferenceEquals(1,1));//object是所有類型的基類,直接用靜態方法也可以
Console.WriteLine(Object.ReferenceEquals(t1,t3));
/*
輸出:
True
False
True
False
True
*/
2.2 成員方法
GetType:獲取對象運行時的Type類型
通過Type結合反射相關知識點可以做很多關於對象的操作
MemberwiseClone:獲取對象的淺拷貝對象
返回一個新的對象,新對象的引用變數會和老對象一致
2.3 虛方法
虛方法可以 override 重寫。
Equals:預設實現還是比較兩者是否為同一個引用,相當於ReferenceEquals
微軟在所有值類型的基類system.ValueType中重寫了該方法,用來比較值相等。我們也可以重寫該方法,定義自己的比較相等的規則
GetHashCode:獲取對象的哈希碼(一種通過演算法算出的表示對象的唯一編碼,不同對象哈希碼有可能一樣,具體值根據哈希演算法決定)
我們可以通過重寫該函數來自己定義對象的哈希碼演算法,正常情況下,我們使用的極少,基本不用
ToString:返回當前對象代表的字元串
調用列印方法Console.WriteLine()時,預設使用的就是對象的Tostring方法後列印出來的內容
3 string
3.1 字元串指定位置獲取
//字元串本質是char數組
string str = "abc";
Console.WriteLine(str[0]);//a
//轉為char數組
char[] chars = str.ToCharArray();
Console.WriteLine(chars[1]);//b
3.2 字元串拼接
str = string.Format("{0}{1}", 1, 23);
Console.WriteLine(str);//123
3.3 正向查找字元串的第一個出現位置
str = "abccdefg";
Console.WriteLine(str.IndexOf("c"));//2 返回下標,從0開始
Console.WriteLine(str.IndexOf("h"));//未找到則返回-1
3.4 反向查找字元串的第一個出現位置
Console.WriteLine(str.LastIndexOf("c"));//3
3.5 移除指定位置及之後的字元
- string 是特殊的引用,特殊的地方在於會在堆中重新分配空間,因此它變我不變,需要賦值來改變內容
str = "abcdefghi";
str.Remove(6);//返回移除後的字元串,並沒有改變原字元串
Console.WriteLine(str);//abcdefghi
str = str.Remove(6);
Console.WriteLine(str);//abcdef
str = str.Remove(4, 2);//兩個參數,分別表示開始位置和字元個數
Console.WriteLine(str);//abcd
3.6 替換指定字元串
str = "abcdefg";
str.Replace("a", "b");
Console.WriteLine(str);//abcdefg
str = str.Replace("a", "b");
Console.WriteLine(str);//bbcdefg
3.7 大小寫轉換
str = "abcdefg";
str.ToUpper();
Console.WriteLine(str);//abcdefg
str = str.ToUpper();
Console.WriteLine(str);//ABCDEFG
str = str.ToLower();
Console.WriteLine(str);//abcdefg
3.8 字元串截取
str = "abcdefg";
//截取指定位置及之後的字元串
str.Substring(2);
Console.WriteLine(str);//abcdefg
str = str.Substring(2);
Console.WriteLine(str);//cdefg
//截取指定位置及之後3個字元
str = str.Substring(2, 3);
Console.WriteLine(str);//efg
3.9 字元串切割
str = "1,2,3,4,5,6,7,8";
string[] strs = str.Split(',');//基於傳入參數將字元串拆分成多個子字元串
foreach(string s in strs)
{
Console.WriteLine(s);//1 2 3 4 5 6 7 8
}
4 stringBulider
4.1 基本概念
- 在頻繁對string重新賦值時會產生記憶體垃圾,C#提供stringBulider用於處理字元串的公共類,可以提升性能
- 在使用 StringBuilder 類時,每次都會對 StringBuilder 對象本身進行操作,而不是生成新的對象,如果需要經常對字元串進行修改推薦使用
- 使用前需要 using System.Text
StringBuilder str = new StringBuilder("123456");
Console.WriteLine(str);
4.2 容量
- StringBuilder 的容量一般比字元串多,每次往字元串里增加時,會存在空的容量裡面
- 如果插入後大於容量,則會自動申請新的記憶體空間,容量大小*2(看記憶體機制),原本的字元串會變成垃圾
Console.WriteLine(str.Length);//6
Console.WriteLine(str.Capacity);//16
//增
str.Append("789");
Console.WriteLine(str);//123456789
Console.WriteLine(str.Length);//9
Console.WriteLine(str.Capacity);//16
//插入
str.Insert(0, "123456789");
Console.WriteLine(str);//123456789123456789
Console.WriteLine(str.Length);//18
Console.WriteLine(str.Capacity);//25 自動申請新的記憶體空間
//刪
str.Remove(0, 3);
Console.WriteLine(str);//456789123456789
//查
Console.WriteLine(str[0]);//4
//改
str[0] = 'X';
Console.WriteLine(str);//X56789123456789
//替換
str.Replace("X", "T");
Console.WriteLine(str);//X56789123456789
//清空
str.Clear();
Console.WriteLine(str);//空
//重新賦值 StringBuilder,這種方法可以避免產生記憶體垃圾
str.Clear();
str.Append("987654321");
Console.WriteLine(str);//987654321
//判斷相等
if (str.Equals("987654321"))//不相等
{
Console.WriteLine("相等");
}
else
{
Console.WriteLine("不相等");
}
5 結構體和類的區別
5.1 區別概述
結構體和類最大的區別是在存儲空間上的,因為結構體是值,類是引用,因此他們的存儲位置一個在棧上,一個在堆上。
- 結構體和類在使用上很類似,結構體甚至可以用面向對象的思想來形容一類對象。
- 結構體具備著面向對象思想中封裝的特性,但是它不具備繼承和多態的特性,因此大大減少了它的使用頻率。
- 由於結構體不具備繼承的特性,所以它不能夠使用protected保護訪問修飾符。
5.2 細節區別
- 結構體是值類型,類是引用類型
- 結構體存在棧中,類存在堆中
- 結構體成員不能使用protected訪問修飾符,而類可以
- 結構體成員變數申明不能指定初始值,而類可以
- 結構體不能申明無參的構造函數,而類可以
- 結構體申明有參構造函數後,無參構造不會被頂掉
- 結構體不能申明析構函數,而類可以
- 結構體不能被繼承,而類可以
- 結構體需要在構造函數中初始化所有成員變數,而類隨意
- 結構體不能被靜static修飾 (不存在靜態結構體) ,而類可以
- 結構體不能在自己內部申明和自已一樣的結構體變數,而類可以
5.3 結構體的特別之處
結構體可以繼承介面,因為介面是行為的抽象。
5.4 如何選擇結構體和類
- 想要用繼承和多態時,直接淘汰結構體,比如玩家、怪物等
- 對象時數據集合時,優先考慮結構體,比如位置、坐標等
- 從值類型和引用類型賦值時的區別上去考慮,比如經常被賦值傳遞的對象,並且改變賦值對象,原對象不想跟著變化時,就用結構體。比如坐標、向量、旋轉等等
6 抽象類和介面的區別
6.1 回顧
抽象類和抽象方法:
- abstract修飾的類和方法
- 抽象類 不能實例化
- 抽象方法只能在抽象類中申明 是個純虛方法 必須在子類中實現
介面:
- interface 自定義類型
- 是行為的抽象
- 不包含成員變數
- 僅包含方法、屬性、索引器、事件,成員都不能實現,建議不寫訪問修飾符,預設public
6.2 相同點
- 都可以被繼承
- 都不能直接實例化
- 都可以包含方法申明
- 子類必須實現未實現的方法
- 都遵循里氏替換原則
6.3 不同點
- 抽象類中可以有構造函數;介面中不能
- 抽象類只能被單一繼承,介面可以被繼承多個
- 抽象類中可以有成員變數;介面中不能
- 抽象類中可以申明成員方法,虛方法,抽象方法,靜態方法;介面中只能申明沒有實現的抽象方法
- 抽象類方法可以使用訪問修飾符;介面中建議不寫,預設public
6.4 如何選擇抽象類和介面
- 表示對象的用抽象類,表示行為拓展的用介面
- 不同對象擁有的共同行為,我們往往可以使用介面來實現
- 舉個例子:動物是一類對象,我們自然會選擇抽象類;而飛翔是一個行為,我們自然會選擇介面