往期文章分享
點(diǎn)擊跳轉(zhuǎn)=>熬夜再戰(zhàn)Android從青銅到王者-UI組件快速搭建App界面 點(diǎn)擊跳轉(zhuǎn)=>熬夜再戰(zhàn)Android從青銅到王者-幾個(gè)適配方案 點(diǎn)擊跳轉(zhuǎn)=>熬夜再戰(zhàn)Android從青銅到王者-開(kāi)發(fā)效率插件篇 點(diǎn)擊跳轉(zhuǎn)=>Unity粒子特效系列-龍卷風(fēng)預(yù)制體做好了,,unitypackage包直接用! 點(diǎn)擊跳轉(zhuǎn)=>姐姐喊我解鎖套娃新技能:FairyGUI在Unity中實(shí)現(xiàn)List嵌套List/立體畫(huà)廊等,,玩出花兒來(lái) 點(diǎn)擊跳轉(zhuǎn)=>Unity新手必備5款寶藏插件–價(jià)值上千元白嫖最新版
??關(guān)于作者
眾所周知,,人生是一個(gè)漫長(zhǎng)的流程,不斷克服困難,,不斷反思前進(jìn)的過(guò)程,。在這個(gè)過(guò)程中會(huì)產(chǎn)生很多對(duì)于人生的質(zhì)疑和思考,于是我決定將自己的思考,,經(jīng)驗(yàn)和故事全部分享出來(lái),,以此尋找共鳴 !??! 專(zhuān)注于Android/Unity和各種游戲開(kāi)發(fā)技巧,以及各種資源分享(網(wǎng)站,、工具,、素材、源碼,、游戲等) 有什么需要?dú)g迎私我,,交流群讓學(xué)習(xí)不再孤單。
??前提
自己出身Android開(kāi)發(fā),,因?yàn)闃I(yè)務(wù)了解也清楚,,所以項(xiàng)目開(kāi)發(fā)很快,就決定業(yè)余時(shí)間學(xué)習(xí)下其他技術(shù),。公司有前端/后端/C++/移動(dòng)端/動(dòng)畫(huà)/模型/硬件/人工智能等多個(gè)部門(mén),,根據(jù)公司發(fā)展和自己興趣,,再加上人們對(duì)帶有立體感的軟件漸漸喜愛(ài),決定擴(kuò)展下此方向,,定下了學(xué)習(xí)c#,。開(kāi)整。
注:因?yàn)椴皇切率?,有不少編程?jīng)驗(yàn),。所以學(xué)習(xí)起來(lái)很快挑重點(diǎn)學(xué)習(xí),記錄也是挑重點(diǎn),。適合做成手冊(cè),,沒(méi)事翻翻。新手警告:閱讀可能有一定困難,。
??實(shí)踐過(guò)程
??C#介紹
源于c語(yǔ)言,簡(jiǎn)單易學(xué),,入門(mén)超快,,減少了煩人的指針,有統(tǒng)一的操作符/修飾符/運(yùn)算符,,使用起來(lái)簡(jiǎn)潔稱(chēng)心,。不僅如此:
- 她是結(jié)構(gòu)化語(yǔ)言,能產(chǎn)生高效率的程序
- 面向組件,,開(kāi)發(fā)快速
- 在多種計(jì)算機(jī)平臺(tái)上編譯,,良好兼容性
- 優(yōu)秀的版本管理控制,安裝卸載和其他程序不影響
- 點(diǎn)Net框架一部分
- 都是她被廣泛應(yīng)用的原因,。
她不僅是按照面向?qū)ο笤O(shè)計(jì)的語(yǔ)言,,而且還類(lèi)型安全,還有更多讓人舒心的功能:
- 自動(dòng)垃圾回收
- 屬性,、事件,、委托等
- 標(biāo)準(zhǔn)庫(kù)
- 簡(jiǎn)單多線程
- Lambad表達(dá)式
雖然c#和Java她們?cè)趦?nèi)部功能實(shí)現(xiàn)及性能上不同,代碼依賴(lài)也不同(Java依賴(lài)JVM,,c#依賴(lài).NET),,但是她們?nèi)匀挥泻芏嘞嗨浦帲@對(duì)于Android出身的我來(lái)說(shuō)更得心應(yīng)手,。
??.NET簡(jiǎn)介
.NET框架是一個(gè)集成,、一個(gè)環(huán)境、一個(gè)非常強(qiáng)大的平臺(tái),,是微軟推出的核心技術(shù),。開(kāi)發(fā)式的體系結(jié)構(gòu),覆蓋的內(nèi)容非常廣: 由上圖看出.NET Framework是.NET最重要的核心技術(shù),。Framework提供了多語(yǔ)言開(kāi)發(fā),,而C#是其中核心語(yǔ)言。
??VS快捷鍵
先來(lái)普及回顧下VS中的常用快捷鍵
Ctrl+K+D:快速對(duì)齊代碼
Ctrl+Z:撤銷(xiāo)
Ctrl+S:保存(一定要經(jīng)常保存,!)
Ctrl+J:快速?gòu)棾鲋悄芴崾?/p>
Shift+End ,、Shift+Home
Ctrl+K+C:注釋所選代碼
Ctrl+K+U:取消對(duì)所選代碼的注釋
F1:轉(zhuǎn)到幫助文檔
折疊冗余代碼:#Region 和#EndRegion(Android Studio也可以自定義折疊代碼 //region //endregion 快捷鍵 Ctrl+Alt+T)
單行注釋?zhuān)?//
多行注釋?zhuān)?要注釋的內(nèi)容/
文檔注釋?zhuān)?/// 多用來(lái)解釋類(lèi)或者方法
??數(shù)據(jù)類(lèi)型
編程基礎(chǔ)就不強(qiáng)調(diào)了,主要看看拼寫(xiě)和其他語(yǔ)言有什么不同就行了 除了這些值類(lèi)型還有引用類(lèi)型,,包含對(duì)象類(lèi)型,,動(dòng)態(tài)類(lèi)型,字符串類(lèi)型
字符串類(lèi)型:string或者String,,注意s大小寫(xiě),,平時(shí)都能用,但也有也小區(qū)別,。
字符串有個(gè)@符號(hào)可以將轉(zhuǎn)移字符當(dāng)成普通字符,,且@符會(huì)保留字符串里面的換行符空格符等
例:string str=”D:\alibaba”; 等價(jià)于string str=@”D:\alibaba”;
動(dòng)態(tài)類(lèi)型:dynami,他會(huì)根據(jù)內(nèi)容自動(dòng)存儲(chǔ)對(duì)應(yīng)類(lèi)型
例:dynamic str=”這是字符”; dynamic number=10; 就像前端的var類(lèi)型
對(duì)象類(lèi)型:ogject,,所有類(lèi)型的最低基類(lèi),,能分配任何類(lèi)型的值,麻煩就是用的時(shí)候可能經(jīng)常得進(jìn)行類(lèi)型轉(zhuǎn)換,。
??轉(zhuǎn)義字符
??運(yùn)算符
仍然是直接上表格圖,,編程基礎(chǔ)。
??判斷/循環(huán)
邏輯判斷仍然是編程老鳥(niǎo)的基基礎(chǔ),,只是簡(jiǎn)單概括一下
判斷語(yǔ)句:if else switch
循環(huán)語(yǔ)句:while for foreach do…while break continue
??訪問(wèn)修飾符
C#可以設(shè)置使用者的訪問(wèn)權(quán)限,,這樣開(kāi)發(fā)者可以指定該模塊或邏輯是公開(kāi),封閉,,還是指定訪問(wèn)者,。不知道其他語(yǔ)言什么樣,跟Java是一樣樣的,。
- public:所有對(duì)象都可以訪問(wèn),;
- private:對(duì)象本身在對(duì)象內(nèi)部可以訪問(wèn);
- protected:只有該類(lèi)對(duì)象及其子類(lèi)對(duì)象可以訪問(wèn)
- internal:同一個(gè)程序集的對(duì)象可以訪問(wèn),;
- protected internal:訪問(wèn)限于當(dāng)前程序集或派生自包含類(lèi)的類(lèi)型,。
??可變類(lèi)型/合并運(yùn)算符
可空類(lèi)型(Nullable):表示其基礎(chǔ)類(lèi)型除了默認(rèn)的值外,再添加一個(gè)null值,。例如:int? num = 1; double? num= new double?();
Null合并運(yùn)算符(,??):如果第一個(gè)操作數(shù)為null,,則返回第二個(gè)操作數(shù),,否則返回第一個(gè),就像Java的,?:運(yùn)算,。
例如 A=B??C 如果B為空則將C賦值給A,,如果B 不為空則將B賦值給A。
??數(shù)組
數(shù)組類(lèi)型是若干個(gè)數(shù)據(jù)類(lèi)型相同的數(shù)據(jù)元素組成的數(shù)據(jù)結(jié)構(gòu),。C#也是分為一維數(shù)組和多維數(shù)組,,多維數(shù)組又包括矩形數(shù)組和交錯(cuò)數(shù)據(jù)。
還有一個(gè)參數(shù)數(shù)組,,可以傳遞未知數(shù)量參數(shù)給函數(shù),。 這個(gè)就像Java中的(int… num)。
例ParamArray app = new ParamArray(); int sum = app.AddElements(512, 720, 250, 567, 889);
數(shù)組類(lèi)型基本是System.Array類(lèi)的派生類(lèi),,快捷鍵Ctrl+左鍵進(jìn)入源碼,,快速學(xué)習(xí)都有什么功能實(shí)現(xiàn)。
??結(jié)構(gòu)體
她能用單一變量存儲(chǔ)多個(gè)數(shù)據(jù)類(lèi)型,,舉例:一個(gè)書(shū)變量,,可以存作者,標(biāo)題,,出版社,,價(jià)錢(qián)等基礎(chǔ)變量。超好理解,,和Java的實(shí)體一樣,就是需要struct關(guān)鍵字來(lái)修飾創(chuàng)建結(jié)構(gòu)體,。特點(diǎn):
- 結(jié)構(gòu)可帶有方法,、字段、索引,、屬性,、運(yùn)算符方法和事件。
- 結(jié)構(gòu)可定義構(gòu)造函數(shù),,但不能定義析構(gòu)函數(shù),。但是,您不能為結(jié)構(gòu)定義無(wú)參構(gòu)造函數(shù),。無(wú)參構(gòu)造函數(shù) (默認(rèn))是自動(dòng)定義的,,且不能被改變。
- 與類(lèi)不同,,結(jié)構(gòu)不能繼承其他的結(jié)構(gòu)或類(lèi),。
- 結(jié)構(gòu)不能作為其他結(jié)構(gòu)或類(lèi)的基礎(chǔ)結(jié)構(gòu)。
- 結(jié)構(gòu)可實(shí)現(xiàn)一個(gè)或多個(gè)接口,。
- 結(jié)構(gòu)成員不能指定為 abstract,、virtual 或 protected。
- 當(dāng)您使用 New 操作符創(chuàng)建一個(gè)結(jié)構(gòu)對(duì)象時(shí),,會(huì)調(diào)用適當(dāng)?shù)臉?gòu)造函數(shù)來(lái)創(chuàng)建結(jié)構(gòu),。與類(lèi)不同,,結(jié)構(gòu)可以不使用 New 操作符即可被實(shí)例化。
- 如果不使用 New 操作符,,只有在所有的字段都被初始化之后,,字段才被賦值,對(duì)象才被使用,。
結(jié)構(gòu)體的字段可以加前綴”_”來(lái)和變量區(qū)分 結(jié)構(gòu)體快捷鍵:首選選中你要自動(dòng)完成的變量,,先按ctrl+R,再按ctrl+E這兩個(gè)組合鍵,可以自動(dòng)生成屬性中的get和set方法
??枚舉
就是命名一組整型常量,,不能繼承或傳遞繼承,,只能當(dāng)常量使用。舉例:enum Number{one,two,three}; 則Number.one等于0 Number.two等于1,,以此類(lèi)推 枚舉可以和結(jié)構(gòu)體結(jié)合:
public struct Person{
public string _name;//字段
public int _age;
public Gender _gender;
}
public enum Gender {
男,
女
}
Person zsPerson;
zsPerson._name = '張三';
zsPerson._age = 21;
zsPerson._gender = Gender.男;
??類(lèi)/函數(shù)
類(lèi)仍然是class修飾,,在class前面可以指定對(duì)類(lèi)及成員的訪問(wèn)規(guī)則,若沒(méi)寫(xiě)則類(lèi)默認(rèn)是internal,,成員訪問(wèn)是private,。 例:public class ClassName { } 函數(shù)和Java同樣含有構(gòu)造函數(shù)和帶參函數(shù),在這多了一個(gè)析構(gòu)函數(shù),,是一個(gè)特殊的成員函數(shù),。是一個(gè)新知識(shí)需要記一下。 析構(gòu)函數(shù)以~作為前綴,,不需要任何修飾符,,不返回值,也不帶參數(shù),,不能繼承或重載,。官方文檔大致意思就是用來(lái)釋放資源的,只不過(guò)并非是在不使用的時(shí)候立即釋放,,她是懶惰的,,垃圾回收機(jī)制會(huì)在適當(dāng)?shù)臅r(shí)候回收,比如內(nèi)存緊張,,關(guān)閉程序等時(shí)候,。這和Android里面的onDestory有異曲同工之妙,同樣的,,也有GC方法來(lái)強(qiáng)制回收,。
??繼承/多重繼承
繼承是面向?qū)ο笤O(shè)計(jì)的最重要概念之一,一個(gè)類(lèi)繼承自另一個(gè)類(lèi),,舉例: class A{ } class B:A{ } B繼承自A,,B可以稱(chēng)為派生類(lèi)也可以稱(chēng)為子類(lèi),A可以稱(chēng)為基類(lèi)也可以稱(chēng)為父類(lèi),。(派生類(lèi)和基類(lèi),,子類(lèi)和父類(lèi)) ,。 B擁有訪問(wèn)A的能力,形象點(diǎn)說(shuō)就是子類(lèi)可以拿到父類(lèi)的財(cái)產(chǎn),,父類(lèi)拿不到子類(lèi)的財(cái)產(chǎn),。 C#不支持多重繼承,我咨詢(xún)過(guò)C++同事,,C++支持多重繼承,。
??多態(tài)
面向?qū)ο蟪绦虻?font color="#02C874" size="5">核心功能之一,是同一個(gè)行為具有多個(gè)不同表現(xiàn)的能力,。C#和Java都是面向?qū)ο蟮?,她們的多態(tài)思想基本是一致的。優(yōu)點(diǎn)多多:
- 消除類(lèi)型間耦合關(guān)系
- 具有可擴(kuò)充性,,增強(qiáng)靈活性
- 接口性,,實(shí)現(xiàn)簡(jiǎn)單
C#包含靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài),靜態(tài)多態(tài)又包含:函數(shù)重載和運(yùn)算符重載,。 函數(shù)重載:就是相同的函數(shù)名有多個(gè)定義,。函數(shù)的參數(shù)類(lèi)型或個(gè)數(shù)不同來(lái)實(shí)現(xiàn)。例如: int test(int num1){} int test(int num1,int num2){} int test(int num1,string str1){} 運(yùn)算符重載看示例更形象,,但是示例代碼多,,就不在這記了,感興趣的可以自己去搜索學(xué)習(xí) 動(dòng)態(tài)重載使用的是用abstract創(chuàng)建的抽象類(lèi),,另一個(gè)事借助關(guān)鍵字virtual修飾的虛方法類(lèi)似實(shí)現(xiàn),。示例
namespace Test
{
abstract class Shape
{
abstract public int area();
}
class Rectangle: Shape
{
private int length;
private int width;
public Rectangle( int a=0, int b=0)
{
length = a;
width = b;
}
//注意著的override
public override int area ()
{
Console.WriteLine('Rectangle 類(lèi)的面積:');
return (width * length);
}
}
class RectangleTester
{
static void Main(string[] args)
{
Rectangle r = new Rectangle(10, 7);
double a = r.area();
Console.WriteLine('面積: {0}',a);
Console.ReadKey();
}
}
}
//虛方法示例
namespace Test
{
class Shape
{
protected int width, height;
public Shape( int a=0, int b=0)
{
width = a;
height = b;
}
// 關(guān)鍵字virtual
public virtual int area()
{
Console.WriteLine('父類(lèi)的面積:');
return 0;
}
}
class Rectangle: Shape
{
public Rectangle( int a=0, int b=0): base(a, b)
{
}
public override int area ()
{
Console.WriteLine('Rectangle 類(lèi)的面積:');
return (width * height);
}
}
class Triangle: Shape
{
public Triangle(int a = 0, int b = 0): base(a, b)
{
}
public override int area()
{
Console.WriteLine('Triangle 類(lèi)的面積:');
return (width * height / 2);
}
}
class Tester
{
static void Main(string[] args)
{
Rectangle r = new Rectangle(10, 7);
Triangle t = new Triangle(10, 5);
c. area ();
c. area ();
Console.ReadKey();
}
}
}
??接口
接口使用interface關(guān)鍵字聲明,和類(lèi)class的聲明差不多,,默認(rèn)是public類(lèi)型的。有個(gè)當(dāng)有多個(gè)類(lèi),,多個(gè)類(lèi)有多個(gè)相同的方法,,使用接口來(lái)實(shí)現(xiàn)方便管理,且不會(huì)丟失,。和Java使用基本是一致的,。示例:
interface ITestInterface
{
void TestInterfaceMethod();
}
public class Test : ITestInterface{
public void TestInterfaceMethod()
{
}
}
??命名空間
Namespace這玩意就是用來(lái)方便管理的,而且在計(jì)算機(jī)中相同的設(shè)計(jì)思想到處可見(jiàn),,比如同一個(gè)文件夾下不同有同名的文件,,你放在不同文件夾下可以有同名文件。 其他編程語(yǔ)言比如Java有包路徑,,不同路徑名字可以有同名的類(lèi),。這種思想方便管理文件/代碼。
namespace first_space
{
class namespace_cl
{ }
//比如這樣,,程序是會(huì)報(bào)錯(cuò)的
class namespace_cl
{ }
}
//但是你是下面的狀態(tài)就不會(huì)報(bào)錯(cuò)
namespace first_space
{
class namespace_cl
{ }
}
namespace second_space
{
class namespace_cl
{ }
}
到這有的人就開(kāi)始有疑問(wèn)了:如果是不同的文件或者想訪問(wèn)其他的空間怎么辦呢,? 細(xì)心的已經(jīng)發(fā)現(xiàn)了,,就和Java的導(dǎo)包一樣,C#使用using導(dǎo)入空間,,在每個(gè)編程文件的最上面幾行都是這樣的引入,,想要哪些空間的功能導(dǎo)入哪個(gè)。 這時(shí)候又有人有疑問(wèn)了,,能不能修仙小說(shuō)那樣天外有天,,天上還有天。能不能命名空間套命名空間,,套套套,,此處禁止套娃。 答案是可以的,,引入的時(shí)候:using namespaceone.namespacetwo 用英文符號(hào).即可,,跟Java包路徑同理。
??預(yù)處理器
從字面理解就是提前對(duì)信息進(jìn)行處理,。她確實(shí)也是這樣的,,她會(huì)根據(jù)你指定的條件,只編譯滿(mǎn)足條件的代碼,,不滿(mǎn)足條件的代碼不編譯,。既區(qū)分了軟件版本,代碼還在一塊,,管理方便,。預(yù)處理指令是#開(kāi)始的,且只能作為開(kāi)頭,,一般指令單獨(dú)占一行,。都有哪些指令在這就不單獨(dú)寫(xiě)了。在Unity中指令挺有用的,,因?yàn)镻C是鍵盤(pán),,Android事件是手勢(shì),用預(yù)處理提前寫(xiě)好不同端的不同實(shí)現(xiàn)代碼(當(dāng)然她們功能可能是一致的),,打包發(fā)布的時(shí)候利人利己,。
??異常
哎呀,這個(gè)老四件套了:try,、catch,、finally 和 throw
- try: 一個(gè) try 塊標(biāo)識(shí)了一個(gè)將被激活的特定的異常的代碼塊。后跟一個(gè)或多個(gè) catch 塊,。
- catch: 程序通過(guò)異常處理程序捕獲異常,。catch 關(guān)鍵字表示異常的捕獲。
- finally: finally 塊用于執(zhí)行給定的語(yǔ)句,不管異常是否被拋出都會(huì)執(zhí)行,。例如,,如果您打開(kāi)一個(gè)文件,不管是否出現(xiàn)異常文件都要被關(guān)閉,。
- throw: 當(dāng)問(wèn)題出現(xiàn)時(shí),,程序拋出一個(gè)異常。使用 throw 關(guān)鍵字來(lái)完成,。
??反射
通俗的講就是可以訪問(wèn)一個(gè)類(lèi)的所有屬性和方法,,且能夠調(diào)用。有人提問(wèn)了:隨便寫(xiě)的public類(lèi)不都是能任意訪問(wèn)調(diào)用的嗎,,這有什么區(qū)別,? 區(qū)別在于一個(gè)是正常寫(xiě)代碼,你知道代碼邏輯和內(nèi)容,,且都在你的掌控之內(nèi),,當(dāng)然能訪問(wèn);而反射不同她能夠訪問(wèn)你不清楚的類(lèi),,比如三方框架你遇到這個(gè)框架里某個(gè)類(lèi)某個(gè)方法沒(méi)有對(duì)外開(kāi)放,,而你又需要使用,就可以用反射把她拋出來(lái),。
優(yōu)點(diǎn):
- 反射提高了程序的靈活性和擴(kuò)展性,。
- 降低耦合性,提高自適應(yīng)能力,。
- 它允許程序創(chuàng)建和控制任何類(lèi)的對(duì)象,,無(wú)需提前硬編碼目標(biāo)類(lèi)。
缺點(diǎn):
- 性能問(wèn)題:使用反射基本上是一種解釋操作,,用于字段和方法接入時(shí)要遠(yuǎn)慢于直接代碼,。因此反射機(jī)制主要應(yīng)用在對(duì)靈活性和拓展性要求很高的系統(tǒng)框架上,普通程序不建議使用,。
- 使用反射會(huì)模糊程序內(nèi)部邏輯,;程序員希望在源代碼中看到程序的邏輯,反射卻繞過(guò)了源代碼的技術(shù),,因而會(huì)帶來(lái)維護(hù)的問(wèn)題,反射代碼比相應(yīng)的直接代碼更復(fù)雜,。
??屬性
總結(jié)一句話(huà),,和Java里實(shí)體的get/set方法一樣的性質(zhì)。
??委托
使用關(guān)鍵字delegate來(lái)修飾,,必須用new關(guān)鍵字來(lái)創(chuàng)建,,且與某個(gè)特定方法關(guān)聯(lián)。 比較官方的說(shuō)法:表示對(duì)具有特定參數(shù)列表和返回類(lèi)型的方法的引用。通過(guò)委托,,可以將方法視為可分配給變量并可作為參數(shù)傳遞的實(shí)體,。 委托還類(lèi)似于其他一些語(yǔ)言中存在的“函數(shù)指針”概念。 與函數(shù)指針不同,,委托是面向?qū)ο笄翌?lèi)型安全的,。 按照自己的理解:委托就是包一個(gè)外殼,操作外殼就是調(diào)用殼內(nèi)的內(nèi)容,。就好像老板讓你板磚,,你委托給另一個(gè)人讓她板磚。這就是委托,。 委托中還能通過(guò)加減號(hào)來(lái)實(shí)現(xiàn)多個(gè),,稱(chēng)之為多播。只有相同類(lèi)型的委托可以合并,。 使用場(chǎng)景:因剛需C#沒(méi)什么實(shí)際經(jīng)驗(yàn),,大家知道有什么好的實(shí)際應(yīng)用環(huán)境嗎
委托示例:
//這個(gè)是聲明個(gè)委托
delegate int NumberChanger(int n);
static int num = 10;
public static int AddNum(int p)
{
num += p;
return num;
}
public static int MultNum(int q)
{
num *= q;
return num;
}
static void Main(string[] args)
{
// 創(chuàng)建委托實(shí)例
NumberChanger nc;
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
// 使用委托對(duì)象調(diào)用方法
nc1(25);
Console.WriteLine('Value of Num: {0}', num);
nc2(5);
Console.WriteLine('Value of Num: {0}', num);
//下面是組播 使用 +或- 符號(hào)操作
nc = nc1;
nc += nc2;
// 調(diào)用多播
nc(5);
Console.WriteLine('Value of Num: {0}', num);
Console.ReadKey();
//輸出結(jié)果為:
//Value of Num: 35
//Value of Num: 175
//Value of Num: 75
}
|