国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Unity3D高級(jí)編程主程手記 學(xué)習(xí)筆記二:C#技術(shù)要點(diǎn)

這篇具有很好參考價(jià)值的文章主要介紹了Unity3D高級(jí)編程主程手記 學(xué)習(xí)筆記二:C#技術(shù)要點(diǎn)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

1.Untiy3D中C#的底層原理

Unity底層在運(yùn)行C#程序時(shí)有兩種機(jī)制:一種是Mono,另一種是IL2CPP。Mono存在的目的是為了跨平臺(tái),因?yàn)樽畛魿#只支持Windows。而IL可以看成是一種匯編語(yǔ)言且完全基于堆棧,必須運(yùn)行在虛擬機(jī)上。也就是說(shuō)C#會(huì)被編譯器編譯成IL,當(dāng)需要他們時(shí)就會(huì)被實(shí)時(shí)的加載到運(yùn)行庫(kù)中,由虛擬機(jī)動(dòng)態(tài)的編譯成匯編代碼(JIT)再進(jìn)行執(zhí)行。

注:Unity中其他的兩門腳本語(yǔ)言Boo,Untiy Script(這兩暫時(shí)還沒(méi)接觸到)也是被編譯成IL后再由Mono虛擬機(jī)解釋并執(zhí)行的。

IL有三種轉(zhuǎn)譯模式:

  1、Just-in-time(JIT)模式:在程序運(yùn)行過(guò)程中將CIL(IL)轉(zhuǎn)譯為機(jī)器碼。

  2、Ahead-of-Time(AOT)模式:將IL轉(zhuǎn)譯成機(jī)器碼并存儲(chǔ)在文件中,此文件并不能完全獨(dú)立運(yùn)行。通常此種模式可產(chǎn)生出絕大部分JIT模式所產(chǎn)生的機(jī)器碼,只有部分例外。例如trampolines或是控制監(jiān)督相關(guān)的代碼任然需要JIT來(lái)運(yùn)行。

  3、完全靜態(tài)編譯:這種模式只支持少數(shù)平臺(tái),它基于AOT編譯模式更進(jìn)一步所產(chǎn)生的機(jī)器碼。完全靜態(tài)編譯可以使得程序在運(yùn)行期間不需要JIT,這種做法適用于IOS,PS3,Xbox360等不允許使用JIT的操作系統(tǒng)

?

Mono使用垃圾回收機(jī)制來(lái)管理內(nèi)存,應(yīng)用程序向垃圾回收器申請(qǐng)內(nèi)存,最終由垃圾回收器決定是否回收。當(dāng)我們向垃圾回收器申請(qǐng)內(nèi)存時(shí),如果發(fā)現(xiàn)內(nèi)存不足,就會(huì)自動(dòng)出發(fā)垃圾回收(也可以主動(dòng)觸發(fā)),垃圾回收器會(huì)遍歷內(nèi)存中所有對(duì)象的引用關(guān)系,如果沒(méi)有被任務(wù)對(duì)象引用則會(huì)釋放內(nèi)存。

3.1.1之后Mono正式將(Simple Generational GC)SGen-GC設(shè)置為默認(rèn)的垃圾回收器,這種方式的主要思想是將對(duì)象分給兩個(gè)內(nèi)存池,一個(gè)新的一個(gè)老的。那些存活時(shí)間長(zhǎng)的對(duì)象都會(huì)放到較老的對(duì)象池中。這種設(shè)計(jì)基于一個(gè)事實(shí),程序經(jīng)常會(huì)申請(qǐng)一些小的臨時(shí)對(duì)象,用完了馬上釋放,而如果某個(gè)對(duì)象一直不釋放則,往往以后的很長(zhǎng)時(shí)間內(nèi)也不會(huì)被釋放。

此外,我們稱IL編碼為托管代碼,這部分代碼由C#自動(dòng)生成,由虛擬機(jī)JIT編譯執(zhí)行,且其中的對(duì)象由GC管理。而使用C++或C#以不安全類型寫的代碼稱為非托管代碼,虛擬機(jī)無(wú)法追蹤到這類代碼對(duì)象,故程序員需要對(duì)這部分代碼的對(duì)象手動(dòng)進(jìn)行管理避免內(nèi)存泄漏的問(wèn)題。(一般情況下,我們使用托管代碼來(lái)編寫游戲邏輯,非托管代碼用于更底層的架構(gòu)、第三方庫(kù)或者是操作系統(tǒng)相關(guān)接口)

?

(中間一部分為 List與Dictionary的源碼剖析,可自行查閱源碼進(jìn)行學(xué)習(xí))

這里只對(duì)部分函數(shù)做結(jié)論和總結(jié):

List:

List使用Array數(shù)組作為底層數(shù)據(jù)結(jié)構(gòu),優(yōu)點(diǎn)是隨機(jī)存儲(chǔ),索引快,缺點(diǎn)是擴(kuò)容時(shí)會(huì)很糟糕,每次針對(duì)數(shù)組進(jìn)行new操作都會(huì)造成內(nèi)存垃圾,會(huì)給GC帶來(lái)負(fù)擔(dān)。

Remove()函數(shù),原理是使用Array.Copy()對(duì)數(shù)組進(jìn)行覆蓋,復(fù)雜度為O(N).

Clear()函數(shù),并不會(huì)對(duì)內(nèi)存進(jìn)行操作真正的刪除元素,而是將對(duì)象內(nèi)的count置0,因?yàn)閷?duì)內(nèi)存進(jìn)行操作會(huì)產(chǎn)生極大的性能消耗。

Enumerator()接口,這是枚舉迭代部分細(xì)節(jié)的接口,其中Enumerator這個(gè)結(jié)構(gòu),每次在獲取迭代器時(shí)都會(huì)被創(chuàng)建出來(lái)。如果大量使用迭代器,例如 foreach語(yǔ)句,就會(huì)產(chǎn)生大量的垃圾。這也就是為什么我們常常說(shuō)要避免在Update()中使用foreach的底層原因。?

Sort()函數(shù),內(nèi)部使用Array.Sort()接口,使用快速排序進(jìn)行排序。

總結(jié):

1.List的效率并不是很高,只是通用性強(qiáng),底層使用的大部分算法都是線性算法。

2.同時(shí)其內(nèi)存分配方式也是不合理的,當(dāng)增加元素需要對(duì)數(shù)組進(jìn)行擴(kuò)充時(shí),原數(shù)組會(huì)被拋棄,這會(huì)給GC帶來(lái)很大的壓力。

3.內(nèi)部代碼是線程不安全的,底層沒(méi)有對(duì)多線程做任何加鎖和限制,如實(shí)現(xiàn)需要多線程操作需要手動(dòng)加鎖。

?

Dictionary:

private struct Entry{
    public int hashCode; // 低31位哈希值,如果未使用則為-1
    public int next; // 下一個(gè)實(shí)例索引,如果是最后一個(gè)則為-1
    public Tkey key; // 實(shí)例的Key
    public TValue value; // 實(shí)例的Value
}

Dictionary使用鏈地址法來(lái)解決哈希沖突,內(nèi)部有兩個(gè)數(shù)組一個(gè)int類型的bucket,還有一個(gè)Entry類型(如上)的entries。

?其中bucket就是下圖中的紫色部分,也就是哈希表。

Entry代表了下圖中綠色部分,每一個(gè)Entry保存自己的Key,Value,以及哈希值,并且可以索引到下一個(gè)實(shí)例(如果有)。

Unity3D高級(jí)編程主程手記 學(xué)習(xí)筆記二:C#技術(shù)要點(diǎn)

總結(jié):

1. Dictionary在效率上與List一樣,最好在實(shí)例化對(duì)象時(shí)就確定大致的數(shù)量,這樣會(huì)減少分配內(nèi)存的頻率。另外,使用值作為鍵值比使用對(duì)象要更高效,因?yàn)轭悓?duì)象的Hash值通常都是由地址內(nèi)存再計(jì)算得到的。

2.從內(nèi)存操作上看,Dictionary增長(zhǎng)速度大約是兩倍,刪除數(shù)據(jù)時(shí),同List一樣不對(duì)內(nèi)存進(jìn)行操作

3.Dictionary是線程不安全的,需要自己進(jìn)行l(wèi)ock操作

2.浮點(diǎn)數(shù)精度問(wèn)題

在實(shí)際使用過(guò)程中,許多人都會(huì)想要使用double類型來(lái)代替float從而解決精度問(wèn)題,但最后往往以失敗告終。

因?yàn)闊o(wú)論是double類型還是float類型,在計(jì)算機(jī)底層存儲(chǔ)都是以二進(jìn)制的形式存儲(chǔ)的,并且存儲(chǔ)的位數(shù)有限(32位/64位)。所以十進(jìn)制在轉(zhuǎn)為二進(jìn)制時(shí)很多數(shù)字會(huì)丟失精度。

2.1精度問(wèn)題可能會(huì)發(fā)生的情況?

(1)數(shù)值比較不相等

  編寫代碼時(shí)通常會(huì)遇到數(shù)值觸及閾值從而觸發(fā)邏輯的情景。例如某一個(gè)變量,從0開(kāi)始,每次加一個(gè)小于0.01的數(shù),加到剛好0.23時(shí)觸發(fā)事件。但是我們不能確定每次加多少,所以結(jié)果會(huì)出現(xiàn)要么比0.23大,要么比0.23小,很難會(huì)出現(xiàn)剛好等于0.23的情況。這時(shí)使用>,<,==等這些符號(hào)就不好處理,如果一定要比較,可以使用ABS()<0.001這樣的方式解決。

(2)數(shù)值計(jì)算不確定

  例如x=1f, y=2f, z = (1f/5555f)* 11110f, 我們預(yù)期x/y應(yīng)當(dāng)是等于z的,但是由于精度問(wèn)題,z結(jié)果可能為0.4999999,這樣x/y與z就不會(huì)相等。

(3)不同設(shè)備計(jì)算結(jié)果不同

  不同計(jì)算機(jī)上操作系統(tǒng),CPU寄存器都不同,計(jì)算時(shí)會(huì)有一定的精度偏差

2.2如何解決精度問(wèn)題?

(1)由一臺(tái)計(jì)算機(jī)進(jìn)行運(yùn)算

  在網(wǎng)絡(luò)同步方面,可以使用一臺(tái)計(jì)算機(jī),例如特定的一臺(tái)服務(wù)器用來(lái)進(jìn)行計(jì)算。

(2)改用int,long類型來(lái)替代浮點(diǎn)數(shù)

  例如,4080,與4.08*1000在數(shù)學(xué)中是完全成立的,我們可以使用4080當(dāng)做4.08進(jìn)行存儲(chǔ),從而避免把數(shù)據(jù)放在小數(shù)點(diǎn)后面(精度截?cái)啵?/p>

(3)用定點(diǎn)數(shù)保持一致性并縮小精度問(wèn)題

  定點(diǎn)數(shù)就是,小數(shù)部分與整數(shù)部分分開(kāi)存儲(chǔ)。從而與方法二一樣,其小數(shù)部分可以使用int或long來(lái)存儲(chǔ),避免小數(shù)截?cái)嗟膯?wèn)題。

struct MyNum{
    int Interger; 
    int Decimal; 
}

(4)用字符串代替浮點(diǎn)數(shù)

  當(dāng)精度要求特別高時(shí),可以使用字符串來(lái)代替浮點(diǎn)數(shù),這種方式不用擔(dān)心越界問(wèn)題,并且還可以自由的控制精度。缺點(diǎn)是很消耗CPU和內(nèi)存。使用字符串代替浮點(diǎn)數(shù),一次計(jì)算量相當(dāng)于好幾萬(wàn)次普通浮點(diǎn)數(shù)。所以當(dāng)精度要求特別高,且計(jì)算次數(shù)不多時(shí)可以考慮這種方法。

3.委托、事件、裝箱、拆箱

3.1委托與事件

  C#中指針被封裝進(jìn)了底層類中,絕大多數(shù)的情況都看不到指針,但回調(diào)函數(shù)依然存在,于是C#中多了委托這一概念。委托可以看成是一種更高級(jí)的函數(shù)指針,它不僅會(huì)把地址指向另一個(gè)函數(shù),而且還能傳遞參數(shù)、獲取返回值等多個(gè)信息。此外,系統(tǒng)還會(huì)為委托對(duì)象自動(dòng)生成同步、異步的調(diào)用方法,開(kāi)發(fā)人員可以使用BeginInvoke(),EndInvoke()來(lái)避開(kāi)Thread類,從而直接使用多線程調(diào)用。

  委托(delegate)不是一個(gè)語(yǔ)言的基本類型,在創(chuàng)建委托的時(shí)候?qū)嶋H上就是在創(chuàng)建一個(gè)delegate類的實(shí)例,這個(gè)delegate類繼承了Sysytem.MulticastDeleate類,類實(shí)例中有BeginInvoke(),EndInvoke(),Invoke()三個(gè)函數(shù),分別表示異步調(diào)用開(kāi)始,結(jié)束,以及直接調(diào)用。

  注:我們不能直接寫一個(gè)類來(lái)繼承Sysytem.MulticastDeleate類,和它的父類Delegate類。官方文檔中的解釋是這兩個(gè)類是特殊的類,編輯器或其他工具可以從他這里繼承,但是你不能直接繼承它。

  Delegate中有一個(gè)變量用來(lái)存儲(chǔ)函數(shù)地址可以認(rèn)為是一個(gè)鏈表。重寫了+=,-=操作符,用來(lái)向這個(gè)鏈表中添加或者刪除元素。也就是把函數(shù)地址加入或者刪除到鏈表中。

  所以delegate關(guān)鍵字只是一個(gè)修飾用詞,背后C#編輯器會(huì)重寫代碼,我們可以認(rèn)為編譯過(guò)程把delegate關(guān)鍵字識(shí)別的對(duì)象轉(zhuǎn)譯成為Delegate類對(duì)象。

  事件(event)則是在delegate上又做了一層封裝,這次封裝的意義是,限制用戶直接操作delegate實(shí)例中的變量的權(quán)限。封裝后,用戶不再能通過(guò)直接賦值的方式(=操作符)來(lái)改變委托變量。只能通過(guò)注冊(cè)或者注銷委托的方式來(lái)增減委托函數(shù)的數(shù)量。通過(guò)這樣的方式更好的維護(hù)了委托的秩序,增加了系統(tǒng)穩(wěn)定性。

3.2裝箱與拆箱?  

  裝箱:把值類型實(shí)例轉(zhuǎn)換成為引用類型實(shí)例。拆箱:把引用類型實(shí)例轉(zhuǎn)為成為值類型實(shí)例。(引用對(duì)象有:string類型,class實(shí)例,數(shù)組)(值對(duì)象有:所有整數(shù),浮點(diǎn)數(shù),bool,struct實(shí)例)

Unity3D高級(jí)編程主程手記 學(xué)習(xí)筆記二:C#技術(shù)要點(diǎn)

?

int a = 5;
object obj = a;

上面就是一個(gè)簡(jiǎn)單的裝箱過(guò)程,因?yàn)閍是一個(gè)值類型,是直接有數(shù)據(jù)的變量,obj為引用變量,指針與內(nèi)存拆分開(kāi)來(lái),把a(bǔ)賦值給obj,實(shí)際上就是obj為自己創(chuàng)建了一個(gè)指針,并指向a的數(shù)據(jù)空間。

a = (int)obj

而這段代碼就是一個(gè)簡(jiǎn)單的拆箱的過(guò)程,相當(dāng)于把obj指向的內(nèi)存空間復(fù)制一份給了a,因?yàn)閍是值引用,所以它不允許指向某個(gè)內(nèi)存空間,只能靠復(fù)制數(shù)據(jù)來(lái)傳遞數(shù)據(jù)。

3.3為何需要裝箱?

  值類型是在聲明之后就立即被初始化的了的,因?yàn)樗坏┞暶?,就有了自己的空間,因此它不可能為null,也不能為null。而引用類型在分配內(nèi)存以后,只是一個(gè)空殼子,可以認(rèn)為是指針,初始化后不指向任何空間,因此默認(rèn)為null

  這里要注意Struct部分,很多人會(huì)把它當(dāng)成是類,而類是引用類型,結(jié)構(gòu)體是值類型。所以a,b同是結(jié)構(gòu)的實(shí)例,a賦值給了b,而b更改數(shù)據(jù)之后a的數(shù)值并沒(méi)有改變。這是因?yàn)閍,b是值類型,各自占用了一片內(nèi)存空間,修改b對(duì)象不會(huì)對(duì)a有影響。在a賦值給b的過(guò)程實(shí)際上是將數(shù)據(jù)原封不動(dòng)復(fù)制一份給了b。

  后面涉及到了堆棧內(nèi)存,所以來(lái)說(shuō)說(shuō)堆棧內(nèi)存是怎么回事?

  棧是存放對(duì)象的一種特殊的容器,它是最基本的數(shù)據(jù)結(jié)構(gòu)之一,遵循先進(jìn)后出的原則。它是一段連續(xù)的內(nèi)存,所以對(duì)棧數(shù)據(jù)定位比較快速;堆則是隨機(jī)分布的空間,定位數(shù)據(jù)時(shí)需要堆內(nèi)存的創(chuàng)建和刪除節(jié)點(diǎn)時(shí)間復(fù)雜度是O(logN)。顯然棧的速度更快,但是棧對(duì)象有嚴(yán)格的聲明周期,并且??臻g有限,會(huì)有棧溢出的問(wèn)題;而堆對(duì)象聲明周期不確定,空間也幾乎沒(méi)有限制。所以并不是所有情況都應(yīng)該使用棧。

  那值類型和引用類型就是堆和棧內(nèi)存分配的區(qū)別嗎?不是!

  引用類型指向的內(nèi)存塊都在堆內(nèi),一般這些內(nèi)存塊都在委托堆內(nèi),這樣便于內(nèi)存塊的回收和控制,GC會(huì)對(duì)這些堆進(jìn)行回收和整理。也有非委托內(nèi)存不歸委托堆管理的部分,這些部分需要自行管理。

  大部分時(shí)候,只有當(dāng)程序邏輯和接口需要更加通用的時(shí)候才需要裝箱。比如一個(gè)含類型為object的參數(shù)的方法,該object可支持任意類型,以便通用。當(dāng)你需要一個(gè)值類型為(如nt32)傳入時(shí),就需要裝箱。又比如一個(gè)非泛型的容器為了保證通用,而將元素類型定義為object,當(dāng)值類型數(shù)據(jù)加入容器時(shí),就需要裝箱。

3.4裝箱的優(yōu)化

  由于裝箱拆箱的過(guò)程,都是生成全新的對(duì)象。不斷地分配和銷毀內(nèi)存不但會(huì)大量消耗CPU,同時(shí)也會(huì)增加內(nèi)存碎片,降低性能。所以我們要盡可能的減少裝箱拆箱。Struct類型比較特殊,它即是值類型,又可以繼承接口,用途多,稍不留神就會(huì)增加性能消耗。以下為Struct的優(yōu)化技巧:

  1)Struct通過(guò)重載函數(shù)來(lái)避免拆箱,裝箱

    如果Strcut沒(méi)有重載一些函數(shù),實(shí)例調(diào)用它們的時(shí)候就會(huì)先裝箱在調(diào)用,所以對(duì)于用到的那些需要調(diào)用的引用方法時(shí),必須重載。

  2)通過(guò)泛型來(lái)避免拆箱、裝箱

    Struct可以繼承Interface接口,我們可以利用Interface做泛型接口,使用泛型來(lái)傳遞參數(shù),這樣就不會(huì)在裝箱后再傳遞值了。比如B,C繼承A,就有了這個(gè)泛型反復(fù)方法 Void Test(T t) where T : A, 以避免使用object引用類型來(lái)傳遞參數(shù)。

  3)通過(guò)繼承統(tǒng)一接口提前拆箱、裝箱,避免多次重復(fù)拆箱、裝箱

    比如Struct A和Struct B都繼承了接口1,我們調(diào)用的方法時(shí)void Test(I i)。當(dāng)調(diào)用Test方法時(shí),傳進(jìn)去的Struct A或 Struct B的實(shí)例相當(dāng)于提前執(zhí)行了裝箱操作,Test方法拿到了參數(shù)后就不用擔(dān)心后面會(huì)進(jìn)行裝箱拆箱操作了。

4.業(yè)務(wù)邏輯優(yōu)化技巧

4.1使用List和Dictionary時(shí)提高效率?

?  每次使用List的Insert,Contain,Remove函數(shù)時(shí),都是會(huì)順序遍歷List的,如果經(jīng)常用到他們就會(huì)有比較大的性能消耗。

  Dictionary也有很多問(wèn)題,它使用一個(gè)Hash沖突方案來(lái)解決關(guān)鍵字的字典組件,因此Hash值與容器中數(shù)組的映射和獲取Hash值的函數(shù)GetHashCode()比較關(guān)鍵。Hash沖突與數(shù)組大小有很大關(guān)系,數(shù)組越大,哈希沖突率越小。在實(shí)際使用過(guò)程中應(yīng)當(dāng)初始化一個(gè)合理的大小,使得Hash沖突不那么頻繁,且放任其自由擴(kuò)容也會(huì)增加GC負(fù)擔(dān);GetHashCode()繼承自基類Object類中的方法,用來(lái)獲取類實(shí)例的Hash值,這個(gè)函數(shù)實(shí)質(zhì)是用算法將內(nèi)存地址轉(zhuǎn)化成哈希值的過(guò)程,不會(huì)有任何緩存的過(guò)程。如果頻繁的使用GetHashCode(),我們應(yīng)當(dāng)要關(guān)注此時(shí)這個(gè)函數(shù)的算力損耗,并確認(rèn)是否可以作為唯一ID。

4.2巧用struct

?  由于struct是一個(gè)值引用對(duì)象,所以傳遞struct時(shí),其實(shí)是在不斷地克隆數(shù)據(jù)。

struct A{
    public int gold;
}

public void main(){
    A a = new A();
    a.gold = 1;
    A b = a;
    b.gold =2;
}

  舉這個(gè)例子,上述struct中有一個(gè)整數(shù)變量gold,實(shí)例a的gold值為1,將a賦值給b后,b的gold設(shè)置為2,此時(shí)a中的gold仍為1,因?yàn)閍和b是兩個(gè)不同的內(nèi)存。

  struct這樣的值變量對(duì)性能優(yōu)化有什么好處呢,如果在函數(shù)中被定義成局部變量,則struct的值類型變量分配的內(nèi)存是在棧上的,棧是連續(xù)內(nèi)存,并且在函數(shù)調(diào)用結(jié)束后,棧的回收非??焖俸秃?jiǎn)單,只有將尾指針置零就可以了,這樣既不會(huì)產(chǎn)生內(nèi)存碎片,又不需要內(nèi)存垃圾回收,CPU讀取數(shù)據(jù)對(duì)連續(xù)內(nèi)存也非常高效。

  除了以上,struct數(shù)組對(duì)提高內(nèi)存訪問(wèn)速度也有所幫助,因?yàn)閮?nèi)部存儲(chǔ)時(shí)連續(xù)存儲(chǔ)的,CPU在讀取數(shù)據(jù)時(shí),連續(xù)內(nèi)存可以幫助我們提高CPU的緩存命中率,因?yàn)镃PU在讀取內(nèi)存時(shí)會(huì)把一個(gè)大塊內(nèi)存放入緩存,當(dāng)下次讀取時(shí)先從緩存中查詢,如果命中則不需要再向內(nèi)存讀取數(shù)據(jù)(緩存比內(nèi)存塊100倍),非連續(xù)內(nèi)存的緩存命中率比較低,而CPU緩存命中率的高低很影響CPU的效率。

4.3盡可能得使用對(duì)象池

  對(duì)象的創(chuàng)建與銷毀都會(huì)引起內(nèi)存分配時(shí)的性能損耗以及垃圾回收時(shí)的艱難。尤其是當(dāng)業(yè)務(wù)邏輯大,數(shù)據(jù)量多的時(shí),垃圾回收需要檢查的內(nèi)存也越多,如果回收后依然內(nèi)存不足,就得向系統(tǒng)請(qǐng)求分配更多內(nèi)存。對(duì)象池的使用并不麻煩,我們是需要在創(chuàng)建銷毀對(duì)象的時(shí)候調(diào)用對(duì)象池管理對(duì)象即可。關(guān)于對(duì)象池的代碼有很多讀者可自行查找相關(guān)代碼。

4.4字符串導(dǎo)致的性能問(wèn)題

?  在C#中由于string是引用類型變量,每次動(dòng)態(tài)創(chuàng)建一個(gè)string,C#都會(huì)在堆內(nèi)存中分配一個(gè)內(nèi)存用于存放字符串。

sting strA = "test";
for(int i=0;i<100;i++){
    string strB = strA + i.ToString();
    string[] strC = strB.Split('e');
    strB = strB + strC[0];
    string strD = string.Format("Hello{0}, this is {1} and {2}."strB,strC[0],strC[1]);  
}

4.5字符串隱藏問(wèn)題

?  字符串隱藏問(wèn)題,當(dāng)兩個(gè)字符比較時(shí),首先會(huì)比較兩個(gè)字符串的地址是否一致(引用變量),如果不一致才會(huì)遍歷字符串各個(gè)字符,如果都一致則返回true。

  該問(wèn)題涉及到ToCharArray(),Clone(),Compare()函數(shù)。string.ToCharArray()返回的char []數(shù)組是一個(gè)新創(chuàng)建的字符串?dāng)?shù)組,與原有的string無(wú)關(guān),我們修改返回的字符串時(shí)不會(huì)影響原來(lái)的string對(duì)象。而Clone和ToString接口則是直接返回該對(duì)象,并不會(huì)重新創(chuàng)建一個(gè)新對(duì)象。?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-482186.html

到了這里,關(guān)于Unity3D高級(jí)編程主程手記 學(xué)習(xí)筆記二:C#技術(shù)要點(diǎn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Unity3D學(xué)習(xí)-Day01-環(huán)境搭建及學(xué)習(xí)資源導(dǎo)入

    Unity3D學(xué)習(xí)-Day01-環(huán)境搭建及學(xué)習(xí)資源導(dǎo)入

    版本選擇可以最新,但是不能太老。因?yàn)楹芏噘Y源都只兼容后續(xù)版本。 總體步驟可以概括為: 一:安裝 1.下載 Unity Hub 2.下載最新的 Unity Personal 正式版 3.登錄 Unity ID 4.安裝編輯器時(shí),保持默認(rèn)安裝選項(xiàng)。(盡量選擇LTS的,我選擇的是2020.3.4) 二:導(dǎo)入 1.下載項(xiàng)目 2.使用 Unit

    2024年02月07日
    瀏覽(98)
  • Unity3D學(xué)習(xí) ② 物體的正常跳躍、二段跳、沖刺

    Unity3D學(xué)習(xí) ② 物體的正常跳躍、二段跳、沖刺

    限制物體在按下跳躍鍵的時(shí)候只能跳躍一次。而不是能夠無(wú)限跳躍。 具體實(shí)現(xiàn)思路是:給地面設(shè)置標(biāo)簽,檢測(cè)物體是否和地面碰撞。 1.1.1 地面(plane)標(biāo)簽設(shè)置 我們?yōu)榱宋矬w能夠正常跳躍,需要給地面添加一個(gè)標(biāo)簽。 點(diǎn)擊地面plane 再點(diǎn)擊 tag 下面的AddTag選項(xiàng) 在AddTag頁(yè)面點(diǎn)擊?

    2023年04月08日
    瀏覽(32)
  • Unity3D學(xué)習(xí)記錄03——Navigation智能導(dǎo)航地圖烘焙

    Unity3D學(xué)習(xí)記錄03——Navigation智能導(dǎo)航地圖烘焙

    首先還是在Package Manager中安裝AI Navigation 接著選擇我們場(chǎng)景的地面,右鍵,找到AI的NavMesh Surface,它會(huì)為我們的Ground添加一個(gè)叫NavMesh Surface的子物體 在Inspector窗口中可以看到它的詳細(xì)的參數(shù): 圖中的R,H為你人物的參數(shù),45°為你的人物可以爬行的最大角度 Agent Type里面可以改

    2024年02月08日
    瀏覽(28)
  • Unity3D學(xué)習(xí)記錄01:URP渲染管線以及3D游戲場(chǎng)景設(shè)置

    Unity3D學(xué)習(xí)記錄01:URP渲染管線以及3D游戲場(chǎng)景設(shè)置

    以下內(nèi)容所使用的版本均為Unity2022.3 先在 Window-Package Manager-Unity Registry 里面搜索添加Universal RP ? Unity中,創(chuàng)建渲染管線的方式為Asset文件夾下右鍵 Create-Readering-URP Asset(with Universal Asset) 會(huì)創(chuàng)建以下兩個(gè)Pipeline: ?接著在圖中的設(shè)置里添加這兩個(gè)渲染管線(Project Setting在Edit窗口下

    2024年02月08日
    瀏覽(102)
  • Unity3D學(xué)習(xí)記錄04——利用射線實(shí)現(xiàn)角色類似LOL的移動(dòng)

    Unity3D學(xué)習(xí)記錄04——利用射線實(shí)現(xiàn)角色類似LOL的移動(dòng)

    首先新建一個(gè)空白的GameObject,掛在一個(gè)MouseManager的腳本 實(shí)現(xiàn)思路: 通過(guò)獲取鼠標(biāo)點(diǎn)擊的位置,獲得該位置的信息,然后使角色移動(dòng)到該位置 MouseManager腳本的代碼如下: ? 代碼解釋: 先創(chuàng)建了一個(gè)Action類型的事件OnMouseClicked 這個(gè)是C#中事件的內(nèi)容,我們可以在滿足條件的時(shí)

    2024年02月08日
    瀏覽(24)
  • 【Unity3D日常開(kāi)發(fā)】Unity3D中協(xié)程的使用

    【Unity3D日常開(kāi)發(fā)】Unity3D中協(xié)程的使用

    推薦閱讀 CSDN主頁(yè) GitHub開(kāi)源地址 Unity3D插件分享 簡(jiǎn)書地址 我的個(gè)人博客 大家好,我是佛系工程師 ☆恬靜的小魔龍☆ ,不定時(shí)更新Unity開(kāi)發(fā)技巧,覺(jué)得有用記得一鍵三連哦。 最近有小伙伴問(wèn)協(xié)程怎么用、怎么寫,我也是會(huì)用會(huì)寫,但是原理不是很明白。 學(xué)習(xí)了一下,總結(jié)出

    2024年02月12日
    瀏覽(31)
  • unity3D基礎(chǔ)操作之01--unity3d窗口界面介紹

    unity3D基礎(chǔ)操作之01--unity3d窗口界面介紹

    提示:文章寫完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔 1、Scene場(chǎng)景編輯窗口; 2、Game游戲運(yùn)行窗口; 3、Hierarchy場(chǎng)景物體列表窗口; 4、Project項(xiàng)目資源列表窗口; 5、Inspector屬性編輯列表窗口; 6、其他常調(diào)節(jié)窗口 在屏幕左上方為場(chǎng)景編輯窗口Scene,在場(chǎng)景編

    2024年02月06日
    瀏覽(31)
  • 【Unity3D-01】 記錄Unity3D調(diào)用外接攝像頭

    【Unity3D-01】 記錄Unity3D調(diào)用外接攝像頭

    最近想在Unity3D上調(diào)用一個(gè)攝像頭,通過(guò)查找資料發(fā)現(xiàn)仙魁XAN和八哥快走開(kāi)的博客符合我的想法,實(shí)現(xiàn)起來(lái)也不難就嘗試了一下 2.1 在這個(gè)工程里新建Canvas 如下圖所示 然后下設(shè)RawImage為載體 2.2 在Assets里面新建一個(gè)腳本命名為PlaneManager.cs 代碼內(nèi)容如下(參考八哥快走開(kāi)的博客)

    2024年02月04日
    瀏覽(30)
  • 【Unity3D小功能】Unity3D中實(shí)現(xiàn)Text顯示版本功能

    【Unity3D小功能】Unity3D中實(shí)現(xiàn)Text顯示版本功能

    推薦閱讀 CSDN主頁(yè) GitHub開(kāi)源地址 Unity3D插件分享 簡(jiǎn)書地址 我的個(gè)人博客 大家好,我是佛系工程師 ☆恬靜的小魔龍☆ ,不定時(shí)更新Unity開(kāi)發(fā)技巧,覺(jué)得有用記得一鍵三連哦。 在項(xiàng)目開(kāi)發(fā)中,會(huì)遇到要控制版本的情況,比如說(shuō)對(duì)比版本號(hào),版本不對(duì)再更新版本的功能,這些就是

    2024年02月05日
    瀏覽(99)
  • 【Unity3D日常開(kāi)發(fā)】Unity3D中實(shí)現(xiàn)單例模式詳解

    【Unity3D日常開(kāi)發(fā)】Unity3D中實(shí)現(xiàn)單例模式詳解

    推薦閱讀 CSDN主頁(yè) GitHub開(kāi)源地址 Unity3D插件分享 簡(jiǎn)書地址 我的個(gè)人博客 大家好,我是佛系工程師 ☆恬靜的小魔龍☆ ,不定時(shí)更新Unity開(kāi)發(fā)技巧,覺(jué)得有用記得一鍵三連哦。 首先,說(shuō)一下,什么是 單例模式(Singleton) 。 單例模式是設(shè)計(jì)模式中常見(jiàn)的一種設(shè)計(jì)模式,目的是為了

    2024年02月02日
    瀏覽(29)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包