111,面向對象
1,面向過程編程:是一種以過程為中心的編程思想分析出解決問題所需要的步驟然后用函數把步驟一步一步實現使用的時候,一個一個依次調用。
2,面向對象編程:面向對象是一種對現實世界理解和抽象的編程方法,把相關的數據和方法組織為一個整體來看待。從更高的層次來進行程序開發更貼近事物的自然運行模式
3,封裝:用程序語言來形容對象。
繼承:復用封裝對象的代碼;兒子繼承父親,復用現成代碼
多態:同樣行為的不同表現,兒子繼承父親的基因但是有不同的行為表現
面向對象編程思想就是:萬物皆對象。用程序來抽象(形容)對象,用面向對象的思想來編程。
222,類和對象
- 什么是類
具有相同特征,具有相同行為,一類事物的抽象類是對象的模板。可以通過類創建出對象
類的關鍵詞 :class
2.類聲明在namespace里面
3. 類聲明的語法
class類名
{
特征一成員變量
行為一成員方法
保護特征一成員屬性
構造函數和析構函數
索引器
運算符重載
靜態成員
}
4,什么是(類)對象
是在方法里面定義:
基本概念:類的聲明 和 類對象(變量)聲明是兩個概念。類的聲明類似 (枚舉 和 結構體的聲明)。相當于聲明了一個自定義變量類型
而對象 是類創建出來的。相當于聲明一個指定類的變量。類創建對象的過程 一般稱為實例化對象。。類對象 都是引用類型的
5.實例化對象基本語法
是在方法里面定義:
類名 變量名;
類名 變量名 = nu11;(nu11代表空)
類名 變量名 = new 類名();
6.實例化對象
是在方法里面定義:
Person p;
Person p2= nu11;//nu11 代表空 不分配堆內存空間
Person p3= new Person();//相當于一個人對象
Person p4 = new Person();//相當于又是一個人對象!
注意:雖然他們是來自一個類的實例化對象。但是他們的 特征 行為等等信息 都是他們獨有的。不要覺得他們是共享了數據 兩個彼此沒有關系。
Machine m = new Machine();
333,成員變量和訪問修飾符
1,訪問修飾符
public - 公共的 自己(內部)和別人(外部)都能訪問和使用
private - 私有的 自己(內部)才能訪問和使用 不寫 默認為private
protected - 保護的 自己(內部)和子類才能訪問和使用
目前決定類內部的成員 的 訪問權限
注意:如果要在類中聲明一個和自己相同類型的成員變量時,不能實例化。
2,成員變量的使用和初始值
值類型來說 數字類型 默認值都是0 bool類型 false 引用類型的 null
默認值的小技巧:直接打印運行就看到了。
Console.WriteLine(default(Person))
333,成員方法的聲明和封裝
成員方法聲明
基本概念:成員方法(函數】用來表現對象行為
1.聲明在類語句塊中
2.是用來描述對象的行為
3.規則和函數聲明規則相同
4.受到訪問修飾符規則影響
5.返回值參數不做限制
6.方法數量不做限制
注意:
1.成員方法不要加static關鍵字
2.成員方法 必須實例化出對象 再通過對象來使用 相當于該對象執行了某個行為
3.成員方法 受到訪問修飾符影響
成員方法的使用
成員方法 必須實例化出對象 再通過對象來使用 相當于該對象執行了某個行為
示例:
class Person
{
public int age;
public string name;
public Person 【】 friends;//數組
public void Speak(string str)
{
Console.WriteLine(“{0}說{1}”, name,str);
}
數組
public void AddFriend(Person)
{
if(friends == null)
{
friends = new Person[]{p };
}
else
{
擴容(數組擴充)
Person[] newFriends=newPerson[friends.Length + 1];
for(int i=0;i<friends.Length; i++)
{
newFriends[i]= friends[i];
}
newFriends[newFriends.Length-1]= p;
friends = newFriends;
}
}
//成員方法 必須實例化出對象 再通過對象來使用 相當于該對象執行了某個行為
class Program
{
static void Main(string[] args)
{
Person p = new Person();
p.name = “lalala”;
p.age = 11;
p.Speak(“雨雨雨雨雨雨”);
Person p2 = new Person();
p2.name = “lalala2”;
p2.age = 21;
p.AddFriend(p2);
for(int i = 0; i < p.friends.Length; i++)
{
cw(p.friends[i].name);
}
}
}
444. 構造,析構,垃圾回收
1,基本概念
在實例化對象時 會調用的用于初始化的函數。如果不寫 默認存在一個無參構造函數。
構造函數的寫法:1.沒有返回值2.函數名和類名必須相同3.沒有特殊需求時 一般都是public的注意:類中是允許自己聲明無參構造函數的 結構體是不允許4.構造函數可以被重載5.this代表當前調用該函數的對象自己
注意: 如果不自己實現無參構造函數而實現了有參構造函數會失去默認的無參構造
可以通過this 重用構造函數代碼:
訪問修飾符 構造函數名(參數列表):this(參數1,參數2…)
2,析構函數基本概念
當引用類型的堆內存被回收時,會調用該函數。對于需要手動管理內存的語言(比如C++),需要在析構函數中做一些內存回收處理。但是C#中存在自動垃圾回收機制Gc。所以我們幾乎不會怎么使用析構函數。除非你想在某一個對象被垃圾回收時,做一些特殊處理
注意:在Unity開發中析構函數幾乎不會使用,所以該知識點只做了解即可。
/基本語法
~類名()
{
}
析構函數 是當垃圾 真正被回收的時候 才會調用的函數
~Person()
{
}
3,垃圾回收
垃圾回收,英文簡寫Gc(Garbage collector)
垃圾回收的過程是在遍歷堆(Heap)上動態分配的所有對象。通過識別它們是否被引用來確定哪些對象是垃圾,哪些對象仍要被使用所謂的垃圾就是沒有被任何變量,對象引用的內容垃圾就需要被回收釋放。垃圾回收有很多種算法,比如引用計數(Reference counting)標記清除(Mark Sweep)標記整理(Mark compact)復制集合(copy Collection)
注意:GC只負責堆(Heap)內存的垃圾回收。引用類型都是存在堆(Heap)中的,所以它的分配和釋放都通過垃圾回收機制來管理。。棧(stack)上的內存是由系統自動管理的。。值類型在棧(stack)中分配內存的,他們有自己的生命周期,不用對他們進行管理,會自動分配和釋放
C#中內存回收機制的大概原理
0代內存 1代內存 2代內存
代的概念:
代是垃圾回收機制使用的一種算法((分代算法)。新分配的對象都會被配置在0代內存中。每次分配都可能會進行垃圾回收以釋放內存(0代內存滿時)
在一次內存回收過程開始時,垃圾回收器會認為堆中全是垃圾,會進行以下兩步:
1.標記對象 從根(靜態字段、方法參數)開始檢査引用對象,標記后為可達對象,未標記為不可達對象不可達對象就認為是垃圾
2.搬遷對象壓縮堆(掛起執行托管代碼線程)釋放未標記的對象 搬遷可達對象 修改引用地址.。。
大對象總被認為是第二代內存,目的是減少性能損耗,提高性能.。不會對大對象進行搬遷壓縮 85000字節(83kb)以上的對象為大對象
堆 heap 棧stack
555,成員屬性
1,基本概念
1.用于保護成員變量
2.為成員屬性的獲取和賦值添加邏輯處理
3.解決”3P“的局限性
public-內外訪問
private-內部訪問
protected-內部和子類訪問
屬性可以讓成員變量在外部
只能獲取 不能修改 或者 只能修改 不能獲取
2語法:
示例:
訪問修飾符 屬性類型 屬性名
{
get{}
set{}
}
實例:
class Person
{
private string name;
private int age;
//屬性使用:帕斯卡命名法。
public string Name
{
get
{
//可在返回之前添加一些邏輯規則。
//意味著這個屬性可以獲取內容
return name;
}
set
{
//可以設置之前添加的一些邏輯規則
//value關鍵字 用于表示 外部傳入的值。
name = value;
}
}
}
3成員屬性中
get和set前可以加訪問修飾符
注意:1.默認不加 會使用屬性申明時的訪問權限2.加的訪問修飾符要低于屬性的訪問權限3.不能讓get和set的訪問權限都低于屬性的權限
4只有一個時 沒必要在前面加訪問修飾符
public bool sex
{
get
{
return sex;//只能得到她
}
}
5.自動屬性
作用:外部能得不能改的特征。如果類中有一個特征是只希望外部能得不能改的又沒什么特殊處理。那么可以直接使用自動屬性
public bool sex
{
get;
set;
}
總結:
1.成員屬性概念:一般是用來保護成員變量的
2.成員屬性的使用和變量一樣 外部用對象點出
3.get中需要return內容:set中用value表示傳入的內容
4.get和set語句塊中可以加邏輯處理
5.get和set可以加訪問修飾符,但是要按照一定的規則進行添加
6.get和set可以只有一個
7.自動屬性是屬性語句塊中只有get和set,一般用于 外部能得不能改這種情況
666,封裝索引器
概念:讓對象可以像數組一樣通過索引訪問其中元素,使程序看起來更直觀,更容易編寫。
訪問修飾符 返回值 this[參數類型 參數名,參數類型 參數名…]
{
//內部的寫法和規則和索引器相同
get{}
set{}
}
可以重載
//總結
//索引器對于我們來說的主要作用
//可以讓我們以中括號的形式范圍自定義類中的元素 規則自己定 訪問時和數組一樣
//比較適用于 在類中有數組變量時使用 可以方便的訪問和進行邏輯處理
結構體支持使用索引器。
777,封裝-靜態成員
1.靜態成員基本概念
//靜態關鍵字static
//用static修飾的 成員變量、方法、屬性等稱為靜態成員
靜態成員的特點是:直接用類名點出使用
2.早已出現的靜態成員
3.自定義靜態成員
在類里面封裝的
class aaa
{
static public floate PI=3.14f;
public static flaot
{
}
}
靜態函數時公共的。。
4.為什么可以直接點出來使用
程序中是不能無中生有的
我們要使用的對象,變量函數都是要在內存中分配內存空間的.之所以要實例化對象,目的就是分配內存空間,在程序中產生一個抽象的對象
靜態成員的特點:程序開始運行時 就會分配內存空間。所以我們就能直接使用。
靜態成員和程序同生共死:只要使用了它,直到程序結束時內存空間才會被釋放:所以一個靜態成員就會有自己唯一的一個“內存小房間”。這讓靜態成員就有了唯一性。在任何地方使用都是用的小房間里的內容,改變了它也是改變小房間里的內容。
6.靜態函數中不能使用非靜態成員
不能直接使用 非靜態成員 否則會報錯
成員變量只能將對象實例化出來后 才能點出來使用 不能無中生有
8.靜態成員對于我們的作用
靜態變量:1.常用唯一變量的中明2.方便別人獲取的對象申明
靜態方法:常用的唯一的方法申明 比如 相同規則的數學計算相關函數
9.常量和靜態變量
const(常量)可以理解為特殊的static(靜態)
相同點:他們都可以通過類名點出使用
不同點:1.const必須初始化,不能修改 static沒有這個規則2.const只能修飾變量、static可以修飾很多3.const一定是寫在訪問修飾符后面的,static沒有這個要求
888. 靜態類
概念用static修飾的類
特點只能包含靜態成員。不能被實例化
作用1.將常用的靜態成員寫在靜態類中 方便使用2.靜態類不能被實例化,更能體現工具類的 唯一性
比如 console就是一個靜態類。
static class00s
{
//靜態成員變量
public static int testIndex = 0,
public static void TestFun()
{
}
public static int TestIndex
{
get;
set;
}
999靜態構造函數
概念在構造函數加上 static 修飾
特點1.靜態類和普通類都可以有2.不能使用訪問修飾符3.不能有參數4.只會自動調用一次
作用在靜態構造函數中初始化 靜態變量
使用1.靜態類中的靜態構造函數
示例:
static class staticclass
{
public static int testInt = 100;
public static int testInt2 = 100;
0 個引用
static staticclass()
{
Console.WriteLine("“靜態構造函數”)
}
}
2.普通類中的靜態構造函數(第一次使用里面的內容時,會自動調用)
class Test
{
public static int testInt = 200;
0 個引用
static Test()
{
Console.WriteLine(“靜態構造”);
}
public fest()
{
Console.WriteLine(“普通構造”)
}
101010拓展方法,
概念:為現有非靜態 變量類型 添加新方法
作用1.提升程序拓展性2.不需要再對象中重新寫方法3.不需要繼承來添加方法4.為別人封裝的類型寫額外的方法
特點1.一定是寫在靜態類中2.一定是個靜態函數3.第一個參數為拓展目標!4.第一個參數用this修飾
語法:訪問修飾符 static 返回值 函數名(this 拓展類名 參數名,參數類型 參數名,參數類型 參數名…
為int拓展了一個成員方法:成員方法 是需要 實例化對象后 才 能使用的。。value 代表 使用該方法的 實例化對象
public static void speakValue(this int value)
{
//拓展的方法 的邏輯
Console.WriteLine("唐老獅為int拓展的方法”+value);
}
:運算符重載
概念:讓自定義類和結構體,能夠使用運算符。
使用關鍵字:operator
特點:1.一定是一個公共的靜態方法2.返回值寫在operator前3.邏輯處理自定義
作用:讓自定義類和結構體對象可以進行運算
注意:1.條件運算符需要成對實現2.一個符號可以多個重載3.不能使用ref和out
語法:public static 返回類型 operator 運算符(參數列表)
實例:
class Point
{
public int x;
public int y;
public static Point operator +(Point p1, Point p2)
{
Point p = new Point();
p.x = p1.x + p2.x;
p.y = p1.y + p2.y;
return p;
}
public static Point operator +(Point p1, int value)
{
Point p = new Point();
p.x = p1.x +value;
p.y = p1.y + value;
return p;
}
//int在前和在后
public static Point operator +(int value,Point p1 )
{
Point p = new Point();
p.x = p1.x + value;
p.y = p1.y + value;
return p;
}
//可重載運算符
//算術運算符
//需要兩個參數還是一個參數
public static Point operator -(Point p1, Point p2)
{
return null;
}
public static Point operator *(Point p1, Point p2)
{
return null;
}
public static Point operator /(Point p1, Point p2)
{
return null;
}
public static Point operator %(Point p1, Point p2)
{
return null;
}
public static Point operator ++(Point p1)
{
return null;
}
public static Point operator --(Point p1)
{
return null;
}
//邏輯運算符:
public static Point operator !(Point p1)
{
return null;
}
//位運算符
public static Point operator |(Point p1, Point p2)
{
return null;
}
public static Point operator &(Point p1, Point p2)
{
return null;
}
public static Point operator ^(Point p1, Point p2)
{
return null;
}
//取反(0,1)
public static Point operator ~(Point p1)
{
return null;
}
public static Point operator <<(Point p1,int num)
{
return null;
}
//條件運算符
//相關符號需要配對實現
public static Point operator >=(Point p1, Point p2)
{
return null;
}
public static Point operator <=(Point p1, Point p2)
{
return null;
}
public static Point operator >(Point p1, Point p2)
{
return null;
}
public static Point operator <(Point p1, Point p2)
{
return null;
}
//不可重載運算符:
//邏輯與&&邏輯或||
//索引符[]
//強轉運算符()
//特殊運算符
//點。 三目運算符 ?:賦值運算符=
}
internal class Program
{
static void Main(string[] args)
{
Point p = new Point();
p.x=1; p.y=1;
Point p2 = new Point();
p2.y=1;p2.x=1;
Point p3=p+p2;
//02按照順序(上面必須有重載)
Point p4=p3+2;
Point p5=2+p3;
}
}
121212內部類和分布類
面對對象————繼承
繼承的規則
概念:一個類A繼承一個類的。。類A將會繼承類B的所有成員。A類將擁有B類的所有特征和行為
被繼承的類稱為 父類、基類、超類
繼承的類稱為子類、派生類
子類可以有自己的特征和行為
特點1.單根性 子類只能有一個父類2.傳遞性 子類可以間接繼承父類的父類
class ChineseTeacher : TeachingTeacher
{
public void Skill()
{
Console.WriteLine(“nianainia”);
}
里氏替換規則
概念:任何父類出現的地方,子類都可以替代
重點:語法表現一父類容器裝子類對象,因為子類對象包含了父類的所有內容
作用:方便進行對象存儲和管理
1里氏替換原則 用父類容器 裝載子類對象
GameObject player = new Player();
is和as
2基本概念 is:判斷一個對象是否是指定類對象返回值:boo1 是為真 不是為假
if( player is Player )
{
}
else if( player is Monster )
{
}
3as:將一個對象轉換為指定類對象
// 返回值:指定類型對象
// 成功返回指定類型對象,
,失敗返回nu11
//基本語法
// 類對象 is 類名
該語句塊 會有一個bool返回值 true和false
// 類對象 as 類名
該語句塊 會有一個對象返回值 對象和nu11
if( player is Player )
{
Player p= player as Player;
p.PlayerAtk();
(player as Player).PlayerAtk();
}
繼承中的構造函數
特點:當申明一個子類對象時,先執行父類的構造函數再執行子類的構造函數
注意:1.父類的無參構造 很重要2.子類可以通過base關鍵字 代表父類 調用父類構造
無參構造函數很重要
子類實例化時 默認自動調用的 是父類的無參構造 所以如果父類無參構造被頂掉 會報
萬物之父
關鍵字:object
概念:object是所有類型的基類,它是一個類(引用類
作用:1.可以利用里氏替換原則,用object容器裝所有對象2.可以用來表示不確定類型,作為函數參數類型
萬物之父的使用:
Father f = new Son();
if( f is son )
{
(f as son).Speak();
}
//引用類型
object o= new son();
//用is as 來判斷和轉換即可
if( o is son )
{
(o as son).Speak();
}
//值類型
object o2 = 1f;
//用強轉
float :fl =(float)o2;
//特殊的string類型
object str=“123123”;
string str2 = str as string; //tostring
//數組
object arr= new int【10】;
int【】arr=(int【】)arr;
裝箱拆箱
發生條件:用bbject存值類型(裝箱),再把object轉為值類型(拆箱)
裝箱:把值類型用引用類型存儲。棧內存會遷移到堆內存中
拆箱:把引用類型存儲的值類型取出來。堆內存會遷移到棧內存中
好處:不確定類型時可以方便參數的存儲和傳遞
壞處:存在內存遷移,增加性能消耗
實例:
//裝箱
object v=3;
//拆箱
int intValue =(int)v;
131313 面向對象–多態
Vob
多態的概念:多態按字面的意思就是“多種狀態”。讓繼承同一父類的子類們 在執行相同方法時有不同的表現(狀態)
主要目的:同一父類的對象 執行相同行為(方法)有不同的表現
解決的問題:讓同一個對象有唯一行為的特征
多態的實現
vob
v:virtual(虛函數)–可以被子類重寫
o:override(重寫)
b:base(父類)
class GameObject
{
public string name;
public GameObject(string name)
{
this.name = name;
}
//虛函數
public virtual void Atk()
{
Console.WriteLine(“游戲對象進行攻擊”);
}
}
class Player : GameObject
{
public Player(string name):base(name)
{
}
//重寫函數
public override void Atk()
{
base.Atk();
Console.WriteLine(“玩家對象進行攻擊”);
}
}
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine();
GameObject p = new Player(“yaya”);
p.Atk();
// (p as Player).Atk();
}
}
抽象類和抽象方法
抽象類
概念:被抽象關鍵字abstract修飾的類
特點:1.不能被實例化的類2.可以包含抽象方法3.繼承抽象類必須重寫其抽象方法
抽象函數 又叫 純虛方法
用 abstract關鍵字修飾的方法
特點:1.只能在抽象類中申明2.沒有方法體3.不能是私有的4.繼承后必須實現 用override重寫
虛方法是可以由我們子類選擇性來實現的 抽象方法必須要實現
虛方法和抽象方法 都可以被子類無限的 去重寫
密封方法
密封方法基本概念:用密封關鍵字sealed 修飾的重寫函數
作用:讓虛方法或者抽象方法之后不能再被重寫
特點:和override一起出現
接口
接口的概念:接口是行為的抽象規范,它也是一種自定義類型。
關鍵字 :interface
接口聲明的規范
1.不包含成員變量
2.只包含方法、屬性、索引器、事件
3.成員不能被實現
4.成員可以不用寫訪問修飾符,不能是私有的
5.接口不能繼承類,但是可以繼承另一個接口
接口的使用規范:1.類可以繼承多個接口2.類繼承接口后,必須實現接口中所有成員
特點:1.它和類的申明類似2.接口是用來繼承的3.接口不能被實例化,但是可以作為容器存儲對象
接口關鍵字:interface
語法:
interface 接口名
{
}
一句話記憶:接口是抽象行為的“基類”
接口命名規范 帕斯卡前面加個I
接口用來繼承
1.類可以繼承1個類,n個接口
2.繼承了接口后 必須實現其中的內容 并且必須是public的
3.實現的接口函數,可以加v再在子類重寫
4.接口也遵循里氏替換原則
接口可以繼承接口
接口繼承接口時,不需要實現。待類繼承接口后 類自己去實現所有內容
顯示實現接口
當一個類繼承兩個接口。但是接口中存在著同名方法時
注意:顯示實現接口時 不能寫訪問修飾符
注意:
1.接口值包含 成員方法、屬性、索引器、事件,并且都不實現,都沒有訪問修飾符
2.可以繼承多個接口,但是只能繼承一個類
3.接口可以繼承接口,相當于在進行行為合并,待子類繼承時再去實現具體的行為
4.接口可以被顯示實現 主要用于實現不同接口中的同名函數的不同表現
5.實現的接口方法 可以加 virtua1關鍵字 之后子類 再重寫
interface IFly
{
void Fly();
string Name
{
get;
set;
}
int this[int index]
{
get; set;
}
event Action doSomthing;
}
//接口是用來繼承
class Animal
{
}
2.繼承了接口后 必須實現其中的內容 并且必須是public的
class Person : Animal, IFly
{
3.實現的接口函數,可以加v再在子類重寫
public void Fly()
{
}
public string Name
{
get;
set;
}
public int this[int index]
{
get
{
return 0;
}
set
{
}
}
public event Action doSomthing;
}
//接口繼承接口時,不需要實現
//待類繼承接口后,類自己去實現所有內容
interface IWalk
{
void Walk();
}
interface IMove:IFly, IWalk
{
}
class Test : IMove
{
public int this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public event Action doSomthing;
public void Fly()
{
throw new NotImplementedException();
}
public void Walk()
{
throw new NotImplementedException();
}
}
interface IAtk
{
void Atk();
}
interface ISuperAtk
{
void Atk();
}
class Plater : IAtk, ISuperAtk
{
顯示實現接口,就是用,接口名”點。“行為名去實現
void IAtk.Atk()
{
throw new NotImplementedException();
}
void ISuperAtk.Atk()
{
throw new NotImplementedException();
}
public void Atk()
{
}
}
class Program
{
static void Main(string[] args)
{
4.接口也遵循里氏替換原則
IFly f = new Person();//裝裝載 子類對象
IWalk walk = new Test();
IMove move = new Test();
IFly fly = new Test();
IAtk ia = new Plater();
ISuperAtk isa = new Plater();
Plater p = new Plater();
(p as IAtk).Atk();
}
}
}
命名空間
概念:名空間是用來組織和重用代碼的
作用:就像是一個工具包,類就像是一件一件的工具,都是聲明在命名空間中的
不同命名空間中相互使用,需要引用命名空間或者指明出處。
例子:using MyGame
MyGame.GanmeObject g = new GameObject();
不同命名空間中可以有同一種類。這個就要知名命名空間的出處。
例子:
MyGame.GanmeObject g = new GameObject();
命名空間可以包裹命名空間
例子:
namespace MyGame
{
namespace UI
{
}
namesp Game
{
}
}
訪問修飾符:
public
internal
abstract 抽象類
sealed 密封
partial 分布類
object 方法:
靜態方法 Equals 判斷兩個對象是否相等。最終的判斷權,交給左側對象的Equa1ls方法。不管值類型引用類型都會按照左側對象Equals方法的規則來進行比較
Console.WriteLine(object.Equals(1,1));
Test t= new Test();
Test t2 =t;
Console.WriteLine(object.Equals(t,t2));
靜態方法ReferenceEquals,比較兩個對象是否是相同的引用,主要是用來比較引用類型的對象。。值類型對象返回值始終是false://比引用
Console.WriteLine(object.ReferenceEquals(t,t2));
object中的成員方法
//普通方法GetType:該方法在反射相關知識點中是非常重要的方法,之后我們會具體的講解這里返回的Type類型。該方法的主要作用就是獲取對象運行時的類型Type,通過Type結合反射相關知識點可以做很多關于對象的操作。
Test t= new Test();
Type type =t.GetType()
//普通方法Memberwiseclone:該方法用于獲取對象的淺拷貝對象,口語化的意思就是會返回一個新的對象,但是新對象中的引用變量會和老對象中一致。
class Test
{
public int i = 1;
public Test2 t2 = new Test2();
public Test clone()
{
return Memberwiseclone() as Test;
}
}
class Test2
{
public int i = 2;
}
Test t2 =t.clone();
Console.WriteLine("克隆對象后”);
Console.WriteLine(“t.i=”+ t.i);
Console.WriteLine(“t.t2.i =”
- t.t2.i);
Console.WriteLine(“t2.i=”+t2.i);
Console.WriteLine("t2.t2.i = - t2.t2.i);
t2.i = 20;
t2.t2.i = 21;
Console.WriteLine(“改變克隆體信息后”);
Console.WriteLine(“t.i=”+ t.i);
Console.WriteLine(“t.t2.i=”+t.t2.i);
Console.WriteLine(“t2.i=”+ t2.i);
Console.WriteLine(“t2.t2.i=”+t2.t2.i);
object中的虛方法
虛方法Equals:默認實現還是比較兩者是否為同一個引用,即相當于ReferenceEquals。但是微軟在所有值類型的基類system.ValueType中重寫了該方法,用來比較值相等。我們也可以重寫該方法,定義自己的比較相等的規則
虛方法GetHashcode:該方法是獲取對象的哈希碼(一種通過算法算出的,表示對象的唯一編碼,不同對象哈希碼有可能一樣,具體值根據哈希算法;我們可以通過重寫該函數來自己定義對象的哈希碼算法,正常情況下,我們使用的極少,基本不用。
虛方法Tostring該方法用于返回當前對象代表的字符串,我們可以重寫它定義我們自己的對象轉字符串規則。該方法非常常用。當我們調用打印方法時,默認使用的就是對象的Tostring方法后打印出來的內容
/總結
/1.虛方法 tostring 自定字符串轉換規則
/2.成員方法 GetType 反射相關
/3.成員方法 Memberwiseclone 淺拷貝
/4.虛方法 Equals 自定義判斷相等的規則
string
注意:所有的方法記得重新賦值,否則不起作用。
1,字符串指定位置獲取:
A:字符串本質是char數組
例子:
string str = “ABC";
CW(str[0]);//打印出來:A
B:轉為char數組
例子:
char[] chars = str.ToCharArray();
for(i=0;i<str.Length;i++)
{
cw(str[i]);
}
2.字符串拼接
str= string.Format(“ {0},{1}”,1,22);
cw(str); // 1,22
3,正向查找字符串位置
str = “我是誰呀你”;
int index = str.IndexOf("誰“);
cw(index);
注意:如果查找的字符串沒有則顯示”-1“
4,反向查找指定字符串位置
例子
str = “我是誰呀你”;
int index = str.LastIndexOf("誰“);
cw(index);
5.移除指定位置后的字符
str = “我是誰呀你”;
int index = str.Remove(4);
cw(index);
int index = str.Remove(1,2);//執行的兩個參數,參數1:開始位置;參數2:字符個數)
cw(index);
6,替換指定字符串
str = “我是誰呀你”;
int index = str.Replace(”啊啊啊啊“);
cw(index);
7,大小寫轉換
小轉大:
str = ”a,b,c,d";
str1=str.ToUper();
cw(str1);
大轉小:
str = ”A,B,C,D";
str1=str.ToLower();
cw(str1);
8.字符串截取
注意:截取從指定字符串位置之后的字符串。
str = “我是誰呀你”;
int index = str.SubString(2);
cw(index);//我是誰
int index = str.SubString(1,2);//執行的兩個參數,參數1:開始位置;參數2:截取的字符個數)
cw(index);// 我呀你
9,字符串切割
str = “1,2,3,4,5,6”;
string [] str = str.Split(‘,’);
for(i=0;i<str.Length;i++)
{
cw(str);
}
打印出來:
1
2
3
4
5
6
這里用到配表居多。
stringbuilder
C#提供的一個用于處理字符串的公共類
//主要解決的問題是:
//修改字符串而不創建新的對象,需要頻繁修改和拼接的字符串可以使用它,可以提升性能
//使用前 需要引用命名空間
//stringBuilder存在一個容量的問題,
每次往里面增加時 會自動擴容
//獲得容量
Console.WriteLine(str.Capacity);
//獲得字符長度
Console.WriteLine(str.Length);
增查刪清查改替換
1,增加
直增:str.Appand(“111”);
拼接增:str.AppendFormat(“{0}{1}”,100,99);
2,插入
str。Insert (0,“里”)//在第0個位置插入一個字符串“里”
3,刪減
str.Remove(0,10);//從第0個位置開始刪掉10個字符串
4,清空
str.Clear();
5,查看
cw(str[0]);//打印出來這個位置的字符串是什么
6,改
str[0]=‘A’;//把字符串的第0位修改為A
7,替換
str.Replace(“1”,“A”);//把字符串1替換成A
8,重新賦值
先清空在添加
str.Clear();
str.Appand(“111”);
cw(str);
9,判斷是否相等
str=“123”;
if(str.Equals(“123”))
{
cw(“xiangdeng)”
}
結構體和類的區別
區別概述
結構體和類最大的區別是在存儲空間上的,因為結構體是值,類是引用。因此他們的存儲位置一個在棧上,一個在堆上‘
結構體和類在使用上很類似,結構體甚至可以用面向對象的思想來形容一類對象。
結構體具備著面向對象思想中封裝的特性,但是它不具備繼承和多態的特性,因此大大減少了它的使
由于結構體不具備繼承的特性,所以它不能夠使用protected保護訪問修飾符。
細節區別
1.結構體是值類型,類是引用類型
2.結構體存在棧中,類存在堆中
3.結構體成員不能使用protected訪問修飾符,而類可以
4.結構體成員變量申明不能指定初始值,而類可以
5.結構體不能申明無參的構造函數,而類可以
6.結構體申明有參構造函數后,無參構造不會被頂掉
7.結構體不能申明析構函數,而類可以
8.結構體不能被繼承,而類可以
9.結構體需要在構造函數中初始化所有成員變量,而類隨意
10.結構體不能被靜態static修飾(不存在靜態結構體),而類可以
11.結構體不能在自己內部申明和自已一樣的結構體變量,而類可以
結構體的特別之處
結構體可以繼承 接口 因為接口是行為的抽象
如何選擇結構體和類
1.想要用繼承和多態時,直接淘汰結構體,比如玩家、怪物等等
2.對象時數據集合時,優先考慮結構體,比如位置、坐標等等
3.從值類型和引用類型賦值時的區別上去考慮,比如經常被賦值傳遞的對象,并且
改變賦值對象,原對象不想跟著變化時,就用結構體。比如坐標、向量、旋轉等等
抽象類和接口的區別
抽象類和抽象方法:abstract修飾的類和方法
抽象類 不能實例化是個純虛函數必須在子類中實現
抽象方法只能在抽象類中聲明
接口interface 自定義類型是行為的抽象不包含成員變量建議不寫訪問修飾符,默認public僅包含方法、屬性、索引器、事件,成員都不能實現
相同點
1.都可以被繼承
2.都不能直接實例化
3.都可以包含方法聲明
4.子類必須實現未實現的方法
5.都遵循里氏替換原則
區別
1.抽象類中可以有構造函數;接口中不能
2.抽象類只能被單一繼承;接口可以被繼承多個
3.抽象類中可以有成員變量;接口中不能
4.抽象類中可以申明成員方法,虛方法,抽象方法,靜態方法;接口中只能申明沒有實現的抽象方法
5.抽象類方法可以使用訪問修飾符;接口中建議不寫,默認public
如何選擇抽象類和接口
表示對象的用抽象類,表示行為拓展的用接口
不同對象擁有的共同行為,我們往往可以使用接口來實現
舉個例子:(抽象大,接口小)動物是一類對象,我們自然會選擇抽象類;而飛翔是一個行為,我們自然會選擇接口。
七大原則
(1)七大原則總體實現目標:高內聚、低耦合。使程序模塊的可重用性,移植性增強
(2)七大原則具體內容
單一職責 類被修改的幾率很大,因此應該專注于單一的功能
開閉原則 對擴展開發,對修改關閉
里氏替換原則 任何父類出現的地方,子類都可以替代
依賴倒轉原則 要依賴于抽象,不要依賴于具體的實現
迪米特原則 一個對象應該對其他對象盡可能少的了解
接口分離原則 一個接口盡量只提供一個對外的功能
合成復用原則 盡量使用對象組合,而不是繼承來達到復用的目的
七大原則:
單一職責原則:一個類只處理自己應該處理的內容,不應該啥都寫在一起。
關閉原則:對拓展開放,對修改封閉。新加功能盡量使加處理而不是修改代碼
里氏原則:任何地方子類都能代替父類,父類容器裝子類。
依賴倒轉原則:不要依賴具體的實現,要依賴抽象和接口
迪米特法則:一個類盡量減少對別的類的了解。盡量少用別的類和自己關聯。
接口隔離原則:一個接口一個行為,不要一個接口N個行為。
合成服用原則:除非設計上需要繼承,否則盡量用組合復用形式。