C#語言基礎-02
寫這兩篇文章的目的是爲了備忘、 C#語言在大學讀書時候學過、當時做過一些東西、但是由於從事的主要工作和C#無關便忘記了。 近來公司增加了Unity業務、 寫Unity主要是C# 和js 想來C# 的語法結構和Java很相似、於是採用了C#語言作爲公司遊戲項目的主要語言。
本系列主要分上中下三篇文章來記錄。 分別牽涉到C# 中的初級、中級、高級內容。
由於本月一直忙於公司的項目、 所以發文就耽擱了, 但是回想五月忙上過去了,還是整理整理髮一篇吧。
本文主要寫一些關於C#語言的中級知識, 如果沒有看過初級的,可以先看上一篇文章,在電腦上敲敲試試,跑一下看看。
1. C# 調試和錯誤處理
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _01_中斷模式下的調試 {
class Program {
void Test()
{
Console.WriteLine("Test method");
}
static void Main(string[] args)
{
int num1 = 34;
int num2 = 67;
Test();
int sum = num1 + num2;
string name = "samuelnotes";
Console.Write(sum);
Console.WriteLine(name);
Console.ReadKey();
}
}
}
在左邊點擊 添加斷點、 運行,調試。 可以盯着具體的變量名稱看運行中的變量內容, 同時可以根據運行時步驟,進行一步一步地查看結果,從而找出程序的問題所在。
2.錯誤與異常處理
來個例子、 沒有不出問題的代碼、 所以錯誤與異常的拋出控制的顯得很重要。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _002_錯誤處理_異常處理_ {
class Program {
static void Main(string[] args) {
try
{
int[] myArray = {1, 2, 3, 4};
int myEle = myArray[4];
}
catch (NullReferenceException e)//在這裏我們雖然寫了異常捕捉的程序,但是我們捕捉的類型不對,所以當發生別的類型的異常的時候,依然會終止程序的運行
{
Console.WriteLine("發生了異常:IndexOutOfRangeException");
Console.WriteLine("您訪問數組的時候,下標越界了");
}
catch//當我們不寫catch的參數的時候,那麼這個catch會捕捉出現的任何異常信息
{
Console.WriteLine("您訪問數組的時候,下標越界了");
}
finally
{
Console.WriteLine("這裏是finally裏面執行的代碼");
}
Console.WriteLine("test");
Console.ReadKey();
}
}
}
再來個例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _003_異常處理_案例2 {
class Program {
static void Main(string[] args)
{
int num1 = 0, num2 = 0;
Console.WriteLine("請輸入第一個數字");
while (true)
{
try {
num1 = Convert.ToInt32(Console.ReadLine());//在try塊中,如果有一行代碼發生了異常,那麼try塊中剩餘的代碼就不會執行了
break;
} catch {
Console.WriteLine("您輸入的不是一個整數,請重新輸入");
}
//break;//把break放在這裏的話,不管發佈發生異常都會執行,因爲try對異常進行了處理
}
Console.WriteLine("請輸入第二個數字");
while (true)
{
try {
num2 = Convert.ToInt32(Console.ReadLine());//在try塊中,如果有一行代碼發生了異常,那麼try塊中剩餘的代碼就不會執行了
break;
} catch {
Console.WriteLine("您輸入的不是一個整數,請重新輸入");
}
//break;//把break放在這裏的話,不管發佈發生異常都會執行,因爲try對異常進行了處理
}
int sum = num1 + num2;
Console.WriteLine(sum);
Console.ReadKey();
}
}
}
3. 面向對象編程-類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _005_面向對象編程_類 {
class Program {
static void Main(string[] args) {
//1,如果要使用一個類的話 要先引入它所在的命名空間,因爲customer位於當前的命名空間下,所以不需要引入,我們可以直接使用Customer
Customer customer1;//在這裏我們使用Customer模板,聲明瞭一個變量(對象)
customer1 = new Customer();//對對象初始化 需要使用new加上類名
customer1.name = "siki";//我們自己定義的類聲明的對象,需要先進行初始化,才能使用
Console.WriteLine(customer1.name);
customer1.Show();//使用對象中的方法
Console.ReadKey();
}
}
}
namespace _005_面向對象編程_類 {
//在這裏我們定義了一個新的類叫做Customer,也可以說定義了一個新的類型叫做Customer
class Customer
{
//數據成員:裏面包含了4個字段
public string name;
public string address;
public int age;
public string buyTime;
//函數成員:定義了一個方法
public void Show()
{
Console.WriteLine("名字:"+name);
Console.WriteLine("年齡:"+age);
Console.WriteLine("地址:"+address);
Console.WriteLine("購買時間:"+buyTime);
}
}
4. 類的定義和聲明
再來個例子
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _006_類的定義和聲明 {
class Program {
static void Main(string[] args) {
//Vehicle car1 = new Vehicle();
//car1.speed = 100;
//car1.Run();
//car1.Stop();
//Console.WriteLine(car1.speed);
//Vector3 v1 = new Vector3();
//v1.x = 1;
//v1.y = 1;
////v1.z = 1;
//v1.SetX(1);
//v1.SetY(1);
//v1.SetZ(1);
Vector3 v1 = new Vector3(1,1,1);
//Console.WriteLine(v1.Length());
//使用屬性
//v1.MyIntProperty = 600;//對屬性設置值
//int temp = v1.MyIntProperty;//對屬性取值
//Console.WriteLine(temp);
//v1.X = 100;
//Console.WriteLine(v1.X);
v1.Name = "siki";
Console.WriteLine(v1.Name);
Console.ReadKey();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _006_類的定義和聲明 {
public class Vector3//設置爲public 這樣才別 的項目中纔可以訪問
{
//我們定義了一個構造函數,那麼編譯器不會爲我們提供構造函數了
public Vector3()
{
Console.WriteLine("Vector3的構造函數被調用了");
}
public Vector3(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
length = Length();
}
//編程規範上 習慣把所有的字段 設置爲private ,只可以在類內部訪問,不可以通過對象訪問
private float x, y, z, length;
private int age;
//private string name;
//public String Name
//{
// get { return name; }
// set { name = value; }
//}
public string Name { get; set; }//編譯器會自動給我們提供一個字段,來存儲name
public int Age
{
set
{
//通過set方法 在設置值之前做一些校驗的工作 屬性的更多好處,需要在寫代碼過程中體會
if (value >= 0)
{
age = value;
}
}
}
public float X// 也可以叫做get set方法
{
get { return x; }
set { x = value; }//如果在get 或者 set前面加上 private,表示這個塊只能在類內部調用
}
//爲字段提供set方法,來設置字段的值
public void SetX(float x)
{
//如果我們直接在方法內部訪問同名的變量的時候,優先訪問最近 (形參)
//我們可以通過this.表示訪問的是類的字段或者方法
this.x = x;
}
public void SetY(float y)
{
this.y = y;
}
public void SetZ(float z)
{
this.z = z;
}
public float Length() {
return (float)Math.Sqrt(x * x + y * y + z * z);
}
//定義屬性
public int MyIntProperty {
set {
Console.WriteLine("屬性中set塊被調用");
Console.WriteLine("在set塊中訪問value的值是:"+value);
}
//如果沒有get塊,就不能通過屬性取值了
get {
Console.WriteLine("屬性中的get塊被調用 ");
return 100;
}
}
}
}
class Vehicle
{
public float speed;
public float maxSpeed;
public float weight;
public void Run()
{
Console.WriteLine("這個車正在以"+speed+"m/s的速度前行");
}
public void Stop()
{
speed = 0;
Console.WriteLine("車輛停止");
}
}
5. 值類型和引用類型
程序運行時候內存的佔用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _008_值類型和引用類型___程序運行時候內存的佔用 {
class Program {
static void Main(string[] args)
{
//Test1();
//Test2();
// Test3();
//Test4();
Test5 ();
Console.ReadKey();
}
static void Test1()
{
int i = 34;
int j = 34;
int temp = 334;
char c = 'a';
bool b = true;
}
static void Test2()
{
int i = 34;
int j = 234;
string name = "siki";
}
static void Test3()
{
string name = "siki";
string name2 = "taikr";
name = name2;
name = "google";
Console.WriteLine(name+":"+name2);
}
static void Test4()
{
Vector3 v = new Vector3();
v.x = 100;
v.y = 100;
v.z = 100;
Vector3 v2 = new Vector3();
v2.x = 200;
v2.y = 200;
v2.z = 200;
v2 = v;
v2.x = 300;
Console.WriteLine(v.x);
}
static void Test5()
{
Vector3[] vArray = new Vector3[]{ new Vector3(), new Vector3(), new Vector3() };//如果數組是一個值類型的數組,那麼數組中直接存儲值,如果是一個引用類型的數組(數組中存儲的是引用類型),那麼數組中存儲的是引用(內存地址)
Vector3 v1 = vArray[0];
vArray[0].x = 100;
v1.x = 200;
Console.WriteLine(vArray[0].x);
}
}
}
/// 空間位置類
class Vector3
{
public float x, y, z;
}
6. 面向對象編程繼承
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _009_面向對象編程_繼承 {
class Program {
static void Main(string[] args) {
//Boss boss = new Boss();
////boss.AI();//繼承:父類裏面所有的數據成員和函數成員都會繼承到子類裏面
//boss.Attack();
//Enemy enemy;
//enemy = new Boss();//父類聲明的對象,可以使用子類去構造 子類聲明的對象不可以使用父類構造
////enemy雖然使用父類進行了聲明,但是使用了子類構造,所以本質上是一個子類類型的,我們可以強制類型轉換轉換成子類類型
//Boss boss = (Boss)enemy;
//boss.Attack();
//Enemy enemy = new Enemy();
//Boss boss =(Boss) enemy;//一個對象是什麼類型的 主要看它是通過什麼構造的 這裏enemy使用了父類的構造函數,所以只有父類中的字段和方法, 不能被強制轉換成子類
//Boss boss = new Boss();
////boss.Attack();
//boss.AI();
//Enemy enemy = new Enemy();
//enemy.AI();
//Enemy boss = new Boss();
//boss.Move();//隱藏方法: 如果使用子類聲明的對象,調用隱藏方法會調用子類的,如果使用父類聲明對象,那麼就會調用父類中的隱藏方法
//Crow crow = new Crow();
//crow.Fly();
//Bird bird = new Crow();//我們可以通過抽象類去聲明對象 但是不可以去構造
//bird.Fly();
Console.ReadKey();
}
}
}
abstract class Bird//一個抽象類 就是一個不完整的模板
{
private float speed;
public void Eat()
{
}
public abstract void Fly();
}
class Boss : Enemy{
//public override void Move()//重寫 : 原來的方法不存在了
//{
// Console.WriteLine("這裏是Boss的移動方法");
//}
public new void Move()//當子類裏面有一個簽名和父類相同的方法的時候,就會把父類中的方法隱藏
{//隱藏: 只是把父類中的方法隱藏了,看不到了,實際這個方法還存在
Console.WriteLine("這裏是Boss的移動方法");
}
public void Attack()
{
//AI();
//Move();
////hp = 100;
//HP = 100;//父類裏面公有是數據和函數成員纔可以在子類裏面訪問
Move();
Console.WriteLine("Boss正在進行攻擊");
}
}
class Crow:Bird {//我們繼承了一個抽象類的時候,必須去實現抽象方法
public override void Fly()
{
Console.WriteLine("烏鴉在飛行");
}
}
class Enemy
{
private float hp;
private float speed;
public float HP
{
get { return hp; }
set { hp = value; }
}
public float Speed
{
get { return speed; }
set { speed = value; }
}
public void AI()
{
//Move();
Console.WriteLine("這裏是Enemy1的公有AI方法");
}
//public virtual void Move()
//{
// Console.WriteLine("這裏是Enemy1的公有Move方法");
//}
public void Move()
{
Console.WriteLine("這裏是Enemy1的公有Move方法");
}
public void A()
{
Console.WriteLine("Enemy A");
}
}
class Type1Enemy:Enemy {
}
class Type2Enemy:Enemy {
}
7. 密封類和密封方法
class BaseCLass {
public virtual void Move()
{
}
}
class DerivedClass:BaseCLass {//sealed密封類無法被繼承
public sealed override void Move()//我們可以把重寫的方法聲明爲密封方法,表示該方法不能 被重寫
{
base.Move();
}
}
8. 派生類的構造函數
class BaseClass
{
private int x;
protected int z;
public BaseClass()
{
Console.WriteLine("base class 無參構造函數");
}
public BaseClass(int x)
{
this.x = x;
Console.WriteLine("x賦值完成");
}
}
class ClassXyz
{
public static int z;//靜態字段
public static void TestMethod()
{
Console.WriteLine("這是靜態方法");
}
private int x;
private int y;
}
class DerivedClass:BaseClass
{
private int y;
public DerivedClass()//調用父類中無參的構造函數 當我們沒有在子類的構造函數中顯示聲明調用父類的構造函數,默認會調用父類中的無參構造函數
{
Console.WriteLine("這個是DerivedClass 無參的構造函數");
}
public DerivedClass(int x, int y):base(x)
{
this.y = y;
base.z = 100;
Console.WriteLine("y賦值完成");
}
}
class Program {
static void Main(string[] args) {//public private
//DerivedClass o1 = new DerivedClass();
//DerivedClass o2= new DerivedClass(1,2);
//BaseClass o1 = new BaseClass();
ClassXyz.z = 100;
Console.WriteLine(ClassXyz.z);
ClassXyz.TestMethod();
Console.ReadKey();
}
}
9. 定義和實現接口
interface IA
{
void Method1();
}
interface IB:IA
{
void Method2();
}
interface IFly
{
void Fly();
void MethodA();
}
class Bird :IFly,IB{
public void Fly()
{
}
public void MethodA()
{
}
public void Method1()
{
}
public void Method2()
{
}
}
10. 列表List的創建和使用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _010_列表List的創建和使用 {
class Program {
static void Main(string[] args) {
//List<int> scoreList = new List<int>();//創建了一個空的列表 通過類型後面的<>來表示這個列表存儲的數據的類型
var scoreList = new List<int>();
//var scoreList = new List<int>(){1,2,3};//創建了一個列表,裏面的初始值有三個分別爲 1 2 3
//Console.WriteLine("capacity:"+scoreList.Capacity+" count:"+scoreList.Count);
//scoreList.Add(12);//向列表中插入數據
//Console.WriteLine("capacity:" + scoreList.Capacity + " count:" + scoreList.Count);
//scoreList.Add(45);
//Console.WriteLine("capacity:" + scoreList.Capacity + " count:" + scoreList.Count);
//Console.WriteLine(scoreList[0]);//根據索引訪問數據
for (int i = 0; i < 20; i++)
{
Console.WriteLine("capacity:" + scoreList.Capacity + " count:" + scoreList.Count);
scoreList.Add( 10 );
}
//Console.WriteLine(scoreList[2]);//索引不存在的時候,會出現異常
Console.ReadKey();
}
}
}
class Program {
static void Main(string[] args)
{
var scoreList = new List<int>();
scoreList.Add(34);
scoreList.Add(334);
scoreList.Add(3344);
scoreList.Add(344);
scoreList.Add(32344);
scoreList.Add(134);
scoreList.Add(334);
//for (int i = 0; i < scoreList.Count; i++)
//{
// Console.Write(scoreList[i]+" ");
//}
foreach (var temp in scoreList)
{
Console.Write(temp+" ");
}
Console.ReadKey();
}
}
11. 操作列表的屬性和方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _011_操作列表的屬性和方法 {
class Program {
static void Main(string[] args) {
var scoreList = new List<int>();
scoreList.Add(100);
scoreList.Add(200);
scoreList.Add(300);
scoreList.Add(100);
foreach (var temp in scoreList)
{
Console.Write(temp+" ");
}
Console.WriteLine();
//scoreList.Insert(3, -1);//向指定索引位置插入元素
//foreach (var temp in scoreList) {
// Console.Write(temp + " ");
//}
//Console.WriteLine();
//scoreList.RemoveAt(0);
//foreach (var temp in scoreList) {
// Console.Write(temp + " ");
//}
//Console.WriteLine();
//int index =scoreList.IndexOf(400);
//Console.WriteLine(index);
//Console.WriteLine( scoreList.IndexOf(100) );
//Console.WriteLine( scoreList.LastIndexOf(100) );
scoreList.Sort();
foreach (var temp in scoreList) {
Console.Write(temp + " ");
}
Console.WriteLine();
Console.ReadKey();
}
}
}
12. 泛型- 泛型類 - 泛型方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _012_泛型_泛型類 {
class ClassA<T,A> {//T代表一個數據類型,當使用classA進行構造的時候,需要制定T的類型
private T a;
private T b;
private A c;
public ClassA(T a, T b )
{
this.a = a;
this.b = b;
}
public string GetSum()
{
return a +""+ b;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _012_泛型_泛型類 {
class Program {
static void Main(string[] args) {
//var o1 = new ClassA<int>(12,34);//當我們利用泛型類構造的時候,需要制定泛型的類型
//string s = o1.GetSum();
//Console.WriteLine(s);
var o2 = new ClassA<string,int>("wwww.","samuelnotes.cn");
Console.WriteLine(o2.GetSum());
Console.ReadKey();
}
}
}
13. 使用泛型和索引器來實現一個我們自己的集合類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _013_泛型方法 {
class Program {
public static string GetSum<T,T2,T3,T4>(T a, T b)
{
return a + "" + b;
}
static void Main(string[] args) {
Console.WriteLine(GetSum<int,int,int,int>(12,34));
Console.WriteLine(GetSum<double,double,double,double>(12.3,34.5));
Console.WriteLine(GetSum<string,string,string,string>("23r,","wer3l2kj"));
Console.ReadKey();
}
}
}
14. 總結
還是那句話、多思考、上手敲代碼、 調試調試、多試試。 如果有問題可以評論區留言共同學習進步。