最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊

從零開始獨(dú)立游戲開發(fā)學(xué)習(xí)筆記(十)--Unity學(xué)習(xí)筆記(四)--微軟C#指南(一)

2021-10-09 02:56 作者:oyishyi  | 我要投稿

學(xué)微軟的東西特別好的一點(diǎn)就是,文檔指南?特別用心。

0. 如何看文檔

對不起,打臉了,微軟這 C# 文檔結(jié)構(gòu)寫的過于意義不明,結(jié)構(gòu)混亂(文檔結(jié)構(gòu),不是文檔本身),幽幽子看了都會(huì)絕食。

為什么這么說呢?

首先我們看一下結(jié)構(gòu):

你們猜一下正確的教程在哪里?你是不是以為是那個(gè)大大的"教程"兩個(gè)字?
然而如果你點(diǎn)開會(huì)發(fā)現(xiàn):

很明顯看標(biāo)題就知道這不是給初學(xué)者看的東西,那么正確的第一個(gè)教程在哪里呢?在這里:

那么你猜第二個(gè)教程在哪里呢?沒錯(cuò),在"基礎(chǔ)"版塊下的教程里。

那么正確的全教程順序是什么呢?

  1. 首先看完"入門"版塊下的教程。

  2. 然后看完"基礎(chǔ)"版塊下的教程。

  3. 然后看完"C#中的新增功能"版塊下的教程。

  4. 然后看完最外層那個(gè)光禿禿的"教程"版塊。

沒錯(cuò),最外層的那個(gè)教程,實(shí)際上指的是最后一個(gè)教程。
相信任何人都會(huì)覺得這結(jié)構(gòu)意義不明。

本篇文章前 5 節(jié)(從 C# 語言介紹 到 程序結(jié)構(gòu))來自"入門"版塊的簡介。看完"簡介"后我發(fā)現(xiàn)下一個(gè)子版塊,也就是"類型" 根本不是給人學(xué)習(xí)看的。經(jīng)過苦苦尋找我才找到真正的初學(xué)者應(yīng)該看的,也就是剛剛上面介紹的順序。真的太難了。微軟罪大滔天。

1. C# 語言介紹

C# 是一門面向?qū)ο?,面向組件的語言。沒別的好說的了。

2. .NET 介紹

C# 在 .NET 上運(yùn)行。

  1. 介紹 .NET 之前應(yīng)該先介紹一下 CLI(不是命令行那個(gè) CLI 哦,是 Common Language Infrastructure),CLI 是一個(gè)標(biāo)準(zhǔn),定義了一個(gè)跨語言的運(yùn)行環(huán)境。

  2. 然后我們才有 CLR(Common Language Runtime),CLR 是微軟開發(fā)的一個(gè) CLI 的實(shí)現(xiàn)。也就是說,CLR 是一個(gè)跨語言的運(yùn)行環(huán)境。(CLI 是標(biāo)準(zhǔn),定義了一個(gè)跨語言的運(yùn)行環(huán)境;CLR 是實(shí)現(xiàn),它就是一個(gè)跨語言的運(yùn)行環(huán)境)

  3. 而 .NET 則是一個(gè)開發(fā)平臺,其中包含了 CLR,同時(shí)還有一堆類庫,以及一些亂七八糟的東西??梢哉f .NET 是一個(gè)統(tǒng)稱。

  4. 既然 .NET 包括了 CLR,也就是說 .NET 并不是和 C# 綁定的。你可以使用任何 CLR 支持的語言在 .NET 上編寫程序,例如 F# 等。

在 .NET 上寫完源代碼后,會(huì)被編譯成 IL 語言。IL 代碼和資源會(huì)被儲存在擴(kuò)展名通常為 dll 的程序集中。

執(zhí)行 C# 程序時(shí),這些程序集會(huì)被加載到 CLR 上(因此想要運(yùn)行 C# 程序必須得有 .NET,這也是為什么很多程序尤其是游戲,經(jīng)常會(huì)讓你去下載 .Netframework 第幾幾幾版本)。然后 CLR 會(huì)對這些 IL 代碼執(zhí)行實(shí)施編譯(JIT,Just-In-Time),編譯成本機(jī)指令。CLR 提供像是垃圾回收,異常處理,資源管理等等這些功能。

IL 是一種中間語言,因此可以和其他 .NET 版本的 F#,C++ 等語言編譯出來的 IL 代碼進(jìn)行交互。一個(gè)程序集中可以有很多模塊,這些模塊由不同語言編寫而成,但是它們之間卻能夠互相引用。

除了 CLR,.NET 還提供了類庫(class libraries)。如果熟悉其他語言的話,很容易理解??傊烁鞣N像是輸入輸出,web框架,字符串控制等等類庫,都被分成對應(yīng)的 namespace。當(dāng)然,除了官方提供的,還有別人或自己寫的第三方庫。

可以看這張圖(如有錯(cuò)誤/模糊不清,歡迎指出):

3. Hello World

先上代碼:

using System;class Hello { ? ?static void Main() { ? ? ? ?Console.WriteLine("Hello, World!"); ? ?} }

雖然只是一個(gè) HelloWorld,但是還是有很多說法的:

  1. 第一行的 using System; 表示使用 System 這個(gè) namespace。namespace 里面可以包含類型,也可以包含其他 namespace。例如第五行里的 Console,其實(shí)就是 System 里包含的類?System.Console,此外 System 里也有其他 namespace 諸如?IO?和?Collections。當(dāng)引用了 namespace 就可以簡寫,比如第五行本來應(yīng)該寫?System.Console.WriteLine,但是由于有了第一行的引用,所以簡寫成?Console.WriteLine?也是可以的。

  2. 我們有一個(gè)類叫做 Hello,然后里面有一個(gè)方法叫做 Main,被 static 修飾符修飾,這個(gè)叫做靜態(tài)方法。靜態(tài)方法不需要實(shí)例就能使用。實(shí)例方法則需要在實(shí)例上運(yùn)行,實(shí)例方法中可以通過 this 來引用實(shí)例。此外,Main 是 C# 規(guī)定的程序入口。程序運(yùn)行的時(shí)候會(huì)自動(dòng)去找這個(gè)方法來運(yùn)行,所以必須有一個(gè)這個(gè)方法。

  3. Console 是一個(gè)類,里面的 WriteLine 是其靜態(tài)方法。Cosole 類由標(biāo)準(zhǔn)庫提供,默認(rèn)情況下編譯器會(huì)自動(dòng)引用標(biāo)準(zhǔn)庫。

4. 類型和變量

C# 有兩種類型。值類型和引用類型。值類型的變量直接包含數(shù)據(jù),而引用類型的變量則儲存對數(shù)據(jù)的引用。

以下是類型的細(xì)分:

  • 值類型:

    • (T1, T2, T3...) 格式的用戶自定義類型

    • 其他所有值類型的擴(kuò)展,包含那個(gè)值類型的所有值和 null

    • struct S {...} 格式的用戶自定義類型

    • enum E {...} 格式的用戶自定義類型。

    • 有符號整型:sbyte, short, int, long

    • 無符號整型:byte, ushory, uint, ulong

    • Unicode 字符:char,代表 UTF-16 代碼單元

    • IEEE 二進(jìn)制浮點(diǎn)數(shù):float,double

    • 高精度十進(jìn)制浮點(diǎn)數(shù):decimal

    • 布爾值:bool

    • 簡單類型:

    • 枚舉類型:

    • 結(jié)構(gòu)類型:

    • 可以為 null 的值類型

    • 元祖值類型:

    • 引用類型:

      • delegate int D(...) 格式的用戶自定義類型

      • 一維,多維,或交錯(cuò):int[], int[,] 或 int[][]

      • interface I {...} 格式的用戶自定義類型

      • 所有類型(包括值類型)的基類:object

      • Unicode 字符串:String,表示 UTF-16 代碼單元序列

      • class C {...} 格式的用戶自定義類型

      • 類類型:(有點(diǎn)拗口,斷句為 類 類型)

      • 接口類型:

      • 數(shù)組類型:

      • 委托類型:

    1. struct 類型和 class 類型都可以包含數(shù)據(jù)成員和函數(shù)成員。區(qū)別在于 struct 是值類型,不需要堆分配。此外,struct 不支持用戶指定的繼承。(為什么并不直接說不支持繼承,而要說不支持用戶指定的既傳承呢?因?yàn)樗?struct 均隱式繼承 object 類,事實(shí)上所有類型都繼承自 object)

    2. interface 可以繼承多個(gè)其他 interface。class 和 struct 也可以同時(shí)實(shí)現(xiàn)多個(gè) interface。

    3. delegate 可以讓方法賦值給變量,甚至作為函數(shù)的參數(shù)。類同于函數(shù)式語言提供的函數(shù)類型。

    4. class,struct,interface,delegate 全部支持泛型。

    可以為 null 的類型無需定義。對于所有沒有 null 值的類型 T,都可以加一個(gè) ? 變成 T? 類型。這樣這個(gè)變量就可以為 null 了。

    C# 采用統(tǒng)一的類型系統(tǒng),因此所有的類型包括值類型都可以看做 object 類型,所有類型都直接或間接派生自 object 類型。

    可以通過裝箱,拆箱來把值類型當(dāng)引用類型來使用。

    int i = 123;object o = i; // 裝箱int j = (int)o; // 拆箱

    裝箱后,值會(huì)被復(fù)制到箱里。拆箱的時(shí)候會(huì)檢查這個(gè)箱里是不是有正確的值類型。

    C# 的統(tǒng)一類型系統(tǒng)實(shí)際上意味著按需將值類型當(dāng)引用類型來引用。如果有庫使用 object,那么實(shí)際上無論是值類型還是引用類型都可以使用。

    5. 程序結(jié)構(gòu)

    C# 中的關(guān)鍵程序結(jié)構(gòu)包括 程序,命名空間,類型,成員,程序集。程序聲明類型,類型包含成員,并被整理進(jìn)命名空間。類型包括 類,接口,結(jié)構(gòu)。成員包括 字段,方法,屬性,事件。編譯完的 C# 實(shí)際會(huì)被打包進(jìn)程序集,視打包成應(yīng)用還是庫,程序集后綴可能為 exe 或 dll。

    6. 字符串的用法

    這里開始正式教程。

    6.1 基本屬性

    1. string 可以用 + 拼接。

    2. 字符串內(nèi)插。類似于其他語言的模板字符串。格式為?$"hello {yourName}",其中 yourName 是變量。

    3. 字符串有屬性 Length,可以得到字符串的長度。格式為?yourName.Length。

    6.2 字符串操作方法

    對字符串進(jìn)行一些修改操作。

    1. Trim, TrimStart, TrimEnd 可以去掉頭尾的空格。

    2. Replace 方法可以替換字符串。替換所有的。

    3. ToUpper 和 ToLower 則是全部轉(zhuǎn)成大寫和小寫。

    操作字符串方法返回的都是新的字符串。

    6.3 搜索字符串

    1. Contains 方法返回該字符串是否包含作為參數(shù)的子字符串。返回值是布爾值。

    2. StartsWith 和 EndsWith 則返回字符串是否以子字符串開頭或結(jié)尾。

    7. 數(shù)字

    1. int.MaxValue 和 int.MinValue 分別表示 int 類型所能承載的最大值和最小值(也就是負(fù)最大值)。

    2. int.MaxValue + 1 == int.MinValue,給最大值 + 1 變成了負(fù)最大值。

    3. 小數(shù)一般都用 double 而不用 float(最好的例子,編譯器遇到小數(shù)常數(shù),會(huì)假定為 double)。double 的范圍極大。高達(dá) 10 的 308 次方(也是一樣通過 double.MaxValue 來查看)。比 long 還長(而且長很多)。

    4. 但是 double 的精度仍然不夠。小數(shù)點(diǎn)后還是只能有 15 位。想要更多的小數(shù)點(diǎn)后位數(shù),就要使用 decimal 類型。decimal 類型的最大值最小值范圍比 double 低很多,但是精度更高。

    decimal a = 1.0M;// 常數(shù)的時(shí)候,如果不加 M,編譯器會(huì)將其當(dāng)做 double 類型Console.WriteLine(1.0/3); // 0.333333333333333Console.WriteLine(1.0M/3); // 0.3333333333333333333333333333

    8. 分支和循環(huán)

    沒什么好說的。

    9. 列表

    因?yàn)橐f的東西挺多,因此從一串代碼開始看起:

    var names = new List<string> {"<name>", "asshole", "joe"};foreach (var name in names) { ? ?Console.WriteLine($"Hello {name}"); }

    輸出為:

    1. List<T>?類型,此類型儲存類型為 T 的一系列元素。

    2. foreach 提供了很方便的遍歷列表的方式。(當(dāng)然,這里 var 完全可以換成 string,當(dāng)你不確定類型的時(shí)候才使用 var)

    9.1 修改列表

    Add 添加元素。
    Remove 刪除元素。
    Count 屬性可以查看列表元素個(gè)數(shù)。(不是 Length)
    實(shí)際上,列表長度有兩種方式。

    9.2 Count 屬性 VS Count() 方法。

    這兩這種方法表現(xiàn)是一致的。硬要說的的話,Count 由于不會(huì)進(jìn)行類型檢查,所以會(huì)比 Count() 快一些。

    9.3 搜索和排序列表

    1. IndexOf() 方法搜索元素所在的索引位置,如果元素不存在則返回 -1。

    2. name.Sort() 會(huì)對列表進(jìn)行排序。(會(huì)改變原來的列表??!這個(gè)方法不返回值?。。?/p>

    10. 如何顯示命令行參數(shù)

    其實(shí)如果做游戲的話,這個(gè)其實(shí)不用學(xué)。但是反正教程就那么幾個(gè)字,看看也不虧。

    命令行參數(shù)會(huì)作為一個(gè)數(shù)組被傳進(jìn) Main 方法。如下:

    static void Main(string[] args) { }

    就這樣,沒了。

    11. 類簡介

    作為一個(gè) OOP 語言,類必然是最重要的概念之一。
    所以現(xiàn)在我們就建立一個(gè)類試試,來表示一個(gè)銀行賬號。

    using System;namespace classes { ? ?public class BankAccount { ? ? ? ?public string Number {get;} ? ? ? ?public string Owner {get; set;} ? ? ? ?public decimal Balance {get;} ? ? ? ? ? ? ? ?public void MakeDeposit (decimal amount, DateTime date, string note) ? ? ? ?{ ? ? ? ? ?} ? ? ? ? ? ? ? ?public void MakeWithdrawal (decimal amount, DateTime date, string note) ? ? ? ?{ ? ? ? ?} ? ? ? ? ? ?} }

    • namespace 用于組織代碼,像是我們現(xiàn)在寫的小代碼,一個(gè) namespace 即可。

    • public 表示能否被其他文件引用。

    BanckAccount 類里:

    1. 前三行是屬性,屬性可以定義一些驗(yàn)證和其他規(guī)則。get,set 表示讀和寫的權(quán)限,如果想讓屬性只讀可以不加 set。

    2. 后兩行是方法。

    11.1 添加賬戶

    我們給其加一個(gè)添加賬戶的功能。也就是實(shí)例化。那么這里要介紹 constructor 了。constructor 是一個(gè)和類名同名的成員。用于初始化實(shí)例(其實(shí) this 可以省略) :

    constructor 和其他方法的區(qū)別,一個(gè)是名字和類名相同,還有一個(gè)就是沒有返回值,void 都不能寫,加了會(huì)被當(dāng)做方法,從而報(bào)錯(cuò),因?yàn)榉椒ú荒芎皖惷?/p>

    試了一下效果:

    11.1.1 賬號號碼(static 修飾符)

    我們有一個(gè)屬性是 Number,這個(gè)屬性不應(yīng)該由用戶提供,而是代碼生成。
    那么一個(gè)簡單地方法是先弄個(gè)初始的 10 位的數(shù)字,然后每添加一個(gè)賬戶就給它 + 1。
    那么我們用這么個(gè)代碼來做到:

    細(xì)節(jié)很多,來解釋:

    1. private,因?yàn)橹挥羞@個(gè)類里會(huì)用到,只是作為一個(gè)初始值。

    2. static,這樣這個(gè)數(shù)字就會(huì)被共享了。有沒有想過,如果沒有加 static,那么每次新賬號都是 1000000001,因?yàn)檫@個(gè)數(shù)會(huì)重新生成。但是如果加上 static,那么這個(gè)屬性就是和 class 綁定的,而不是和實(shí)例綁定的。換句話說就是 static 修飾的屬性可以讓我們在實(shí)例之間共享數(shù)據(jù)。

    然后把構(gòu)造函數(shù)改成這樣既可(其實(shí) this 可以省略,但為了區(qū)分 static 和別的區(qū)別還是加上):

    • 由于現(xiàn)在在類內(nèi),所以直接調(diào)用 initialAccountNumber 即可,如果是在外面的話,就要用 BankAccount.initialAccountNumber。當(dāng)然了,由于我們是 private,就算在外面也調(diào)用不了就是了。

    測試一下效果:

    11.2 創(chuàng)建存款和取款

    單純地改變 Balance 沒意思,也不合理。我們先創(chuàng)建一個(gè)類叫做 transaction。用這個(gè)來記錄 Balancce 的變化。

    然后我們創(chuàng)建一個(gè)屬性用于存儲每個(gè)賬號所有的歷史 transaction。

    然后我們修改 Balance 屬性。讓其等于所有 transaction 計(jì)算后的結(jié)果。

    然后終于開始寫方法,這個(gè)時(shí)候會(huì)引入 exception:

    然后我們需要對 constructor 進(jìn)行修改,因?yàn)槌跏蓟?balance 也需要改變了(此時(shí) Balance 可以去掉 set 變成只讀了):

    Date.Now 獲取當(dāng)前時(shí)間,注意是屬性不是方法。

    11.3 測試

    使用 try catch 可以捕獲錯(cuò)誤:

    看起來差不多,但是沒有說未捕獲的異常了。而且這個(gè)錯(cuò)誤是我自己主動(dòng)打印出來的。

    11.4 log 所有 transaction

    看代碼:

    StringBuilder 類型的 AppendLine 方法會(huì)自動(dòng)在每一行后面加空格。然后我們再用制表符調(diào)整縮進(jìn)。 測試效果如下:

    12. 繼承和多態(tài)

    OOP 有四個(gè)重要的特性。Abstraction,Encapsulation,Inheritance, Polymorphism。前面兩個(gè)在上一節(jié)已經(jīng)講過了,這一節(jié)講后兩個(gè)。

    依舊拿剛才的銀行賬號類來講解。

    12.1 繼承

    我們要新建 3 種銀行賬號類型。儲蓄卡,信用卡和禮品卡。首先我們先將它們創(chuàng)建,并繼承之前的類:

    1. 每一個(gè)新的類都已經(jīng)有和 BankAccount 相同的屬性和方法了。

    2. 可以看到報(bào)錯(cuò)了,因?yàn)槲覀冃枰袠?gòu)造函數(shù)。而且這個(gè)構(gòu)造函數(shù)不止要初始化現(xiàn)在這個(gè)類,還要初始化基類。

    可以看下面的代碼:

    1. 構(gòu)造函數(shù)里也要和繼承一樣的格式,但是繼承的類直接用 base 代替,而不是寫基類的名字。

    2. base 里參數(shù)不寫類型,因?yàn)檫@是在調(diào)用而不是在聲明。

    3. 原理就是,這個(gè)構(gòu)造函數(shù)會(huì)調(diào)用基類的構(gòu)造函數(shù),傳參則直接從當(dāng)前構(gòu)造函數(shù)里拿。

    4. 有些時(shí)候基類可能有多個(gè)構(gòu)造函數(shù),這個(gè)語法可以選擇用哪種構(gòu)造函數(shù)。

    12.2 多態(tài)

    假設(shè)每一張卡都會(huì)在月底做一些事情,但是每張卡做的事情不一樣。那么我們使用多態(tài)來完成這件事。
    首先我們?nèi)サ紹ankAccount 類,加上以下 virtual 方法:

    • virtual 關(guān)鍵字表示這個(gè)方法之后可能會(huì)被繼承類重新實(shí)現(xiàn)。既然是可能,也就是說你也可以在基類里寫一些代碼,然后不覆蓋。

    • 在繼承類里使用 override 關(guān)鍵字來覆蓋掉方法。

    • 也可以把 virtual 換成 abstract,來讓繼承類強(qiáng)制覆蓋這個(gè)方法。(不過那樣的話基類本身也得是 abstract 類型,具體之后再講吧)

    繼承類里也可以調(diào)用基類的方法:

    不過我們現(xiàn)在不需要用,前兩張卡實(shí)現(xiàn)代碼如下:

    對于禮品卡,規(guī)則比較多,因此需要更改一些別的,比如我們先修改構(gòu)造函數(shù):

    這里因?yàn)槲覀冎挥幸痪洌虼耸∪チ舜罄ㄌ?,使用?=> 也就是 lambda 運(yùn)算符。
    然后我們再改寫 MonthlyTask 方法:

    測試一下 禮品卡 和 儲蓄卡:

    但是當(dāng)測試信用卡的時(shí)候,出問題了:

    這很 resonable,因?yàn)?BankAccount 限制不能取走比 Banlance 更多的錢。于是我們需要修改 BankAccount 了:

    • readonly 屬性和只給一個(gè) get 的屬性的區(qū)別在于。前者只能在構(gòu)造函數(shù)階段賦值,一旦初始化之后就無法更改了。而后者則可以在 class 內(nèi)部進(jìn)行更改。不過對外都是作為只讀屬性來看。

    • 這里我們有兩個(gè)構(gòu)造函數(shù),第一個(gè)構(gòu)造函數(shù)接受 3 個(gè)參數(shù);第二個(gè)接受兩個(gè)參數(shù),同時(shí)使用?:this()?語法來調(diào)用上一個(gè)構(gòu)造函數(shù)。然后這里我們只需要調(diào)用第一個(gè)構(gòu)造函數(shù)(以第三個(gè)參數(shù)為 0 的形式),不需要做別的事,所以就用?:this() {}?了。

    然后我們修改 MakeWithdrawal:

    然后我們在 CreditCardAccount 里可以修改成這樣:

    12.2.1 protocted


    現(xiàn)在想讓信用卡能夠超過 creditLimit,可以用 virtual 方法。在 BankAccount 里,更改 MakeWithdrawal 方法:

    public void MakeWithdrawal(decimal amount, DateTime date, string note){ ? ?if (amount <= 0) ? ?{ ? ? ? ?throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive"); ? ?} ? ?var overdraftTransaction = CheckWithdrawalLimit(Balance - amount < minimumBalance); ? ?var withdrawal = new Transaction(-amount, date, note); ? ?allTransactions.Add(withdrawal); ? ?if (overdraftTransaction != null) ? ? ? ?allTransactions.Add(overdraftTransaction); }protected virtual Transaction? CheckWithdrawalLimit(bool isOverdrawn) { ? ?if (isOverdrawn) ? ?{ ? ? ? ?throw new InvalidOperationException("Not sufficient funds for this withdrawal"); ? ?} ? ?else ? ?{ ? ? ? ?return default; ? ?} }

    我寫在這里是因?yàn)槲倚陆ǖ捻?xiàng)目用的是 C# 7.3,而只有 C# 8.0 才有"可以為null的引用類型"的支持。

    這里除了修改 MakeWithdrawal 方法以外,還添加了一個(gè)新的方法。這個(gè)方法前的修飾符是 protected 和 virtual。

    • protected 和 public,private 是一類的,代表著這個(gè)方法只能被繼承類調(diào)用。

    • virtual 代表著這個(gè)方法可以被繼承類覆蓋。

    加在一起就是只能被繼承類調(diào)用,同時(shí)可以被覆蓋。

    于是我們在 CreditCardAccount 里覆蓋它:

    public override Transaction? CheckWithdrawalLimit(bool isOverdrawn) ? ?=> isOverdrawn ? ?? new Transaction(-20, DateTime.Now, "Apply overdraft fee") ? ?: default; ? ?

    通過這樣的方式,把代碼分離出成一個(gè) virtual 方法,然后 override,就可以做出不同的行為了。


    從零開始獨(dú)立游戲開發(fā)學(xué)習(xí)筆記(十)--Unity學(xué)習(xí)筆記(四)--微軟C#指南(一)的評論 (共 條)

    分享到微博請遵守國家法律
    漯河市| 灵山县| 河西区| 廊坊市| 中江县| 漳平市| 阜康市| 石景山区| 米泉市| 阳江市| 上思县| 东丰县| 新郑市| 云安县| 易门县| 泰兴市| 城固县| 昌黎县| 怀仁县| 乌兰浩特市| 西林县| 财经| 赣榆县| 遵义县| 桃园市| 宁阳县| 申扎县| 滦南县| 自贡市| 巴塘县| 盈江县| 重庆市| 临夏市| 包头市| 阿合奇县| 厦门市| 桃源县| 巫山县| 兴隆县| 克拉玛依市| 昌吉市|