Unity3D中的C#程式設計初級
一、前言
這篇文章主要是給零基礎想要Unity入門的關於C#程式設計的一些意見
二、參考文章
unity中的C#程式設計-零基礎(Unity2017)
三、正文
1、支援Unity3D的程式語言
2、程式設計工具(IDE)
3、建立C#程式碼
4、場景的儲存和指令碼的儲存
5、關於日誌輸出(指控制輸出,其中Log有三類:正常、警告、錯誤輸出)
6、變數與常量
7、方法的定義和呼叫
8、方法中的引數,返回值
9、類的定義
10、列舉型別:
11、元件的建立與使用
1、支援Unity3D的程式語言
C#、JavaScript、UnityScript
先說C#與JavaScript,因為JavaScript是動態的,肯定不如編譯的C#好,但是JavaScript更快捷一點, JavaScript適合個人開發,敏捷快速。c#適合公司開發,規範嚴謹。
然後說說這個C#和Unity內建的UnityScript
UnityScript脫胎於.Net平臺的第三方語言Boo,差距可能是全方位,立體式的。社群支援,程式碼維護,甚至是編譯出來的CIL程式碼質量都可能有很大的差距。另外從Unity5.0版本開始就會停止對Boo的文件支援。同時消失的還有從選單建立Boo指令碼的選項“Create Boo Script”。從U3D團隊對Boo的態度,也可以窺見和Boo聯絡密切的UnityScript未來的走勢。
2、程式設計工具(IDE)
Visual Studio 全系列
Visual Studio Code
Xamarin Studio
這個主要是在Mac上使用的IDE,因為在Mac上不能使用VS,MonoDevelop也不能輸入中文,就挺難受的,就可以使用XamarinStudio,關於這個IDE使用可以參考這篇文章。http://www.xuanyusong.com/archives/3545
MonoDevelop
Unity3D內建的編輯器,操作感覺一般,但是勝在方便,在安裝Unity3D的時候就可以一起安裝了,不用另外安裝IDE了
JetBrains Rider
一款強大的強大的跨平臺C#編輯器,官網https://www.jetbrains.com/zh/dotnet/promo/unity/
3、建立C#程式碼
在工程目錄下右鍵點選,選擇Create->C# Script
在任意物件上,點選Add Component->New Script
這個是建立成功後的初始指令碼的樣子
4、場景的儲存和指令碼的儲存
快捷鍵F2 點選場景名或者指令碼名字可以重新命名
快捷鍵Ctrl+S 快速儲存場景或者儲存指令碼
狀態列中顯示“*”號的都是未儲存的
編輯器意外奔潰,場景未來得及儲存?
這時可以開啟工程目錄,找到/Temp/_Backupscenes/資料夾,可以看到有字尾名為.backup的檔案,將該檔案的字尾名改為.unity拖拽到專案檢視,即可還原編輯器崩潰前的場景。
5、關於日誌輸出(指控制輸出,其中Log有三類:正常、警告、錯誤輸出)
print
是MonoBehaviour的一個成員,必須繼承MonoBehaviour才能使用,通過反編譯可以看到print的方法為
public static void print(object message)
{
Debug.Log(message);
}
說明print方法還是通過Debug.Log實現的,print就是Debug.Log的一個簡單封裝。
Debug.Log
輸出log資訊,可以在執行的時候檢視關鍵資料的變化
Debug.LogWarning
輸出警告資訊
Debug.LogError
輸出錯誤資訊
6、變數與常量
因為兩個比較相似,就放一塊說
變數
一個變數只不過是一個供程式操作的儲存區的名字。在 C# 中,每個變數都有一個特定的型別,型別決定了變數的記憶體大小和佈局。範圍內的值可以儲存在記憶體中,可以對變數進行一系列操作。
常量
常量是固定值,程式執行期間不會改變。常量可以是任何基本資料型別,比如整數常量、浮點常量、字元常量或者字串常量,還有列舉常量。
常量可以被當作常規的變數,只是它們的值在定義後不能被修改。
變數的型別
型別 舉例
整數型別 sbyte、byte、short、ushort、int、uint、long、ulong 和 char
浮點型 float 和 double
十進位制型別 decimal
布林型別 true 或 false 值,指定的值
空型別 可為空值的資料型別
其他變數型別 列舉enum,引用型別變數class,結構體型別struct
變數的定義
int i, j, k;
char c, ch;
float f, salary;
double d;
變數的初始化
int d = 3, f = 5; /* 初始化 d 和 f. */
byte z = 22; /* 初始化 z. */
double pi = 3.14159; /* 宣告 pi 的近似值 */
char x = 'x'; /* 變數 x 的值為 'x' */
例項
namespace VariableDefinition
{
class Program
{
static void Main(string[] args)
{
short a;
int b ;
double c; /* 實際初始化 */
a = 10;
b = 20;
c = a + b;
Console.WriteLine("a = {0}, b = {1}, c = {2}", a, b, c);
Console.ReadLine();
}
}
}
編譯執行結果:
a = 10, b = 20, c = 30
1
常量的定義
const double pi = 3.14159; // 常量宣告
1
常量的型別
整數常量
整數常量可以是十進位制、八進位制或十六進位制的常量。字首指定基數:0x 或 0X 表示十六進位制,0 表示八進位制,沒有字首則表示十進位制。
整數常量也可以有字尾,可以是 U 和 L 的組合,其中,U 和 L 分別表示 unsigned 和 long。字尾可以是大寫或者小寫,多個字尾以任意順序進行組合。
212 /* 合法 */
215u /* 合法 */
0xFeeL /* 合法 */
078 /* 非法:8 不是一個八進位制數字 */
032UU /* 非法:不能重複字尾 */
85 /* 十進位制 */
0213 /* 八進位制 */
0x4b /* 十六進位制 */
30 /* int */
30u /* 無符號 int */
30l /* long */
30ul /* 無符號 long */
浮點常量
一個浮點常量是由整數部分、小數點、小數部分和指數部分組成。您可以使用小數形式或者指數形式來表示浮點常量。
這裡有一些浮點常量的例項:
3.14159 /* 合法 */
314159E-5L /* 合法 */
510E /* 非法:不完全指數 */
210f /* 非法:沒有小數或指數 */
.e55 /* 非法:缺少整數或小數 */
使用小數形式表示時,必須包含小數點、指數或同時包含兩者。使用指數形式表示時,必須包含整數部分、小數部分或同時包含兩者。有符號的指數是用 e 或 E 表示的。
字元常量
字元常量是括在單引號裡,例如,’x’,且可儲存在一個簡單的字元型別變數中。一個字元常量可以是一個普通字元(例如 ‘x’)、一個轉義序列(例如 ‘\t’)或者一個通用字元(例如 ‘\u02C0’)。
在 C# 中有一些特定的字元,當它們的前面帶有反斜槓時有特殊的意義,可用於表示換行符(\n)或製表符 tab(\t)。在這裡,列出一些轉義序列碼:
轉義序列 含義
\\ \ 字元
\’ ’ 字元
\” ” 字元
\? ? 字元
\a Alert 或 bell
\b 退格鍵(Backspace)
\f 換頁符(Form feed)
\n 換行符(Newline)
\r 回車
\t 水平製表符 tab
\v 垂直製表符 tab
\ooo 一到三位的八進位制數
\xhh … 一個或多個數字的十六進位制數
例項:
namespace EscapeChar
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello\tWorld\n\n");
Console.ReadLine();
}
}
}
編譯執行結果:
Hello World
1
字串常量
字串常量是括在雙引號 “” 裡,或者是括在 @”” 裡。字串常量包含的字元與字元常量相似,可以是:普通字元、轉義序列和通用字元
使用字串常量時,可以把一個很長的行拆成多個行,可以使用空格分隔各個部分。
這裡是一些字串常量的例項。下面所列的各種形式表示相同的字串。
string a = "hello, world"; // hello, world
string b = @"hello, world"; // hello, world
string c = "hello \t world"; // hello world
string d = @"hello \t world"; // hello \t world
string e = "Joe said \"Hello\" to me"; // Joe said "Hello" to me
string f = @"Joe said ""Hello"" to me"; // Joe said "Hello" to me
string g = "\\\\server\\share\\file.txt"; // \\server\share\file.txt
string h = @"\\server\share\file.txt"; // \\server\share\file.txt
string i = "one\r\ntwo\r\nthree";
string j = @"one
two
three";
例項:
using System;
namespace DeclaringConstants
{
class Program
{
static void Main(string[] args)
{
const double pi = 3.14159; // 常量宣告
double r;
Console.WriteLine("Enter Radius: ");
r = Convert.ToDouble(Console.ReadLine());
double areaCircle = pi * r * r;
Console.WriteLine("Radius: {0}, Area: {1}", r, areaCircle);
Console.ReadLine();
}
}
}
編譯執行結果:
Enter Radius:
Radius: 3, Area: 28.27431
7、方法的定義和呼叫
方法的定義
語法如下:
<Access Specifier> <Return Type> <Method Name>(Parameter List)
{
Method Body
}
下面是方法的各個元素:
Access Specifier:訪問修飾符,這個決定了變數或方法對於另一個類的可見性。
Return type:返回型別,一個方法可以返回一個值。返回型別是方法返回的值的資料型別。如果方法不返回任何值,則返回型別為 void。
Method name:方法名稱,是一個唯一的識別符號,且是大小寫敏感的。它不能與類中宣告的其他識別符號相同。
Parameter list:引數列表,使用圓括號括起來,該引數是用來傳遞和接收方法的資料。引數列表是指方法的引數型別、順序和數量。引數是可選的,也就是說,一個方法可能不包含引數。
Method body:方法主體,包含了完成任務所需的指令集。
例項:
下面的程式碼片段顯示一個函式 FindMax,它接受兩個整數值,並返回兩個中的較大值。它有 public 訪問修飾符,所以它可以使用類的例項從類的外部進行訪問。
class NumberManipulator
{
public int FindMax(int num1, int num2)
{
/* 區域性變數宣告 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
...
}
方法的呼叫
using System;
namespace CalculatorApplication
{
class NumberManipulator
{
public int FindMax(int num1, int num2)
{
/* 區域性變數宣告 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
static void Main(string[] args)
{
/* 區域性變數定義 */
int a = 100;
int b = 200;
int ret;
NumberManipulator n = new NumberManipulator();
//呼叫 FindMax 方法
ret = n.FindMax(a, b);
Console.WriteLine("最大值是: {0}", ret );
Console.ReadLine();
}
}
}
編譯執行後的結果:
最大值是: 200
1
您也可以使用類的例項從另一個類中呼叫其他類的公有方法。例如,方法 FindMax 屬於 NumberManipulator 類,您可以從另一個類 Test 中呼叫它。
using System;
namespace CalculatorApplication
{
class NumberManipulator
{
public int FindMax(int num1, int num2)
{
/* 區域性變數宣告 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
}
class Test
{
static void Main(string[] args)
{
/* 區域性變數定義 */
int a = 100;
int b = 200;
int ret;
NumberManipulator n = new NumberManipulator();
//呼叫 FindMax 方法
ret = n.FindMax(a, b);
Console.WriteLine("最大值是: {0}", ret );
Console.ReadLine();
}
}
}
編譯執行的結果:
最大值是: 200
1
遞迴方法的呼叫
一個方法可以自我呼叫。這就是所謂的 遞迴。下面的例項使用遞迴函式計算一個數的階乘:
using System;
namespace CalculatorApplication
{
class NumberManipulator
{
public int factorial(int num)
{
/* 區域性變數定義 */
int result;
if (num == 1)
{
return 1;
}
else
{
result = factorial(num - 1) * num;
return result;
}
}
static void Main(string[] args)
{
NumberManipulator n = new NumberManipulator();
//呼叫 factorial 方法
Console.WriteLine("6 的階乘是: {0}", n.factorial(6));
Console.WriteLine("7 的階乘是: {0}", n.factorial(7));
Console.WriteLine("8 的階乘是: {0}", n.factorial(8));
Console.ReadLine();
}
}
}
編譯執行後的結果:
6 的階乘是: 720
7 的階乘是: 5040
8 的階乘是: 40320
引數傳遞
當呼叫帶有引數的方法時,您需要向方法傳遞引數。在 C# 中,有三種向方法傳遞引數的方式:
方式 描述
值引數 這種方式複製引數的實際值給函式的形式引數,實參和形參使用的是兩個不同記憶體中的值。在這種情況下,當形參的值發生改變時,不會影響實參的值,從而保證了實引數據的安全。
引用引數 這種方式複製引數的記憶體位置的引用給形式引數。這意味著,當形參的值發生改變時,同時也改變實參的值。
輸出引數 這種方式可以返回多個值。
按值引數傳遞
這是引數傳遞的預設方式。在這種方式下,當呼叫一個方法時,會為每個值引數建立一個新的儲存位置。
實際引數的值會複製給形參,實參和形參使用的是兩個不同記憶體中的值。所以,當形參的值發生改變時,不會影響實參的值,從而保證了實引數據的安全。下面的例項演示了這個概念:
using System;
namespace CalculatorApplication
{
class NumberManipulator
{
public void swap(int x, int y)
{
int temp;
temp = x; /* 儲存 x 的值 */
x = y; /* 把 y 賦值給 x */
y = temp; /* 把 temp 賦值給 y */
}
static void Main(string[] args)
{
NumberManipulator n = new NumberManipulator();
/* 區域性變數定義 */
int a = 100;
int b = 200;
Console.WriteLine("在交換之前,a 的值: {0}", a);
Console.WriteLine("在交換之前,b 的值: {0}", b);
/* 呼叫函式來交換值 */
n.swap(a, b);
Console.WriteLine("在交換之後,a 的值: {0}", a);
Console.WriteLine("在交換之後,b 的值: {0}", b);
Console.ReadLine();
}
}
}
編譯執行後的結果:
在交換之前,a 的值:100
在交換之前,b 的值:200
在交換之後,a 的值:200
在交換之後,b 的值:100
結果表明,swap 函式內的值改變了,且這個改變可以在 Main 函式中反映出來。
按輸出傳遞引數
return 語句可用於只從函式中返回一個值。但是,可以使用 輸出引數 來從函式中返回兩個值。輸出引數會把方法輸出的資料賦給自己,其他方面與引用引數相似。
下面的例項演示了這點:
using System;
namespace CalculatorApplication
{
class NumberManipulator
{
public void getValue(out int x )
{
int temp = 5;
x = temp;
}
static void Main(string[] args)
{
NumberManipulator n = new NumberManipulator();
/* 區域性變數定義 */
int a = 100;
Console.WriteLine("在方法呼叫之前,a 的值: {0}", a);
/* 呼叫函式來獲取值 */
n.getValue(out a);
Console.WriteLine("在方法呼叫之後,a 的值: {0}", a);
Console.ReadLine();
}
}
}
編譯執行後的結果:
在方法呼叫之前,a 的值: 100
在方法呼叫之後,a 的值: 5
1
2
提供給輸出引數的變數不需要賦值。當需要從一個引數沒有指定初始值的方法中返回值時,輸出引數特別有用。請看下面的例項,來理解這一點
using System;
namespace CalculatorApplication
{
class NumberManipulator
{
public void getValues(out int x, out int y )
{
Console.WriteLine("請輸入第一個值: ");
x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("請輸入第二個值: ");
y = Convert.ToInt32(Console.ReadLine());
}
static void Main(string[] args)
{
NumberManipulator n = new NumberManipulator();
/* 區域性變數定義 */
int a , b;
/* 呼叫函式來獲取值 */
n.getValues(out a, out b);
Console.WriteLine("在方法呼叫之後,a 的值: {0}", a);
Console.WriteLine("在方法呼叫之後,b 的值: {0}", b);
Console.ReadLine();
}
}
}
編譯執行後的結果:
請輸入第一個值:
7
請輸入第二個值:
8
在方法呼叫之後,a 的值: 7
在方法呼叫之後,b 的值: 8
8、方法中的引數,返回值
方法中引數的型別有三種
in型引數
int 型引數通過值傳遞的方式將數值傳入方法中,即我們在Java中常見的方法。
ref型引數
該種型別的引數傳遞變數地址給方法(引用傳遞),傳遞前變數必須初始化。
該型別與out型的區別在與:
1).ref 型傳遞變數前,變數必須初始化,否則編譯器會報錯, 而 out 型則不需要初始化
2).ref 型傳遞變數,數值可以傳入方法中,而 out 型無法將資料傳入方法中。換而言之,ref 型有進有出,out 型只出不進。
out 型引數
與 ref 型類似,僅用於傳回結果。
注意:
1). out型資料在方法中必須要賦值,否則編譯器會報錯。
eg:如下圖若將程式碼中的sum1方法的方法體
改為 a+=b; 則編譯器會報錯。原因:out 型只出不進,在沒給 a 賦值前是不能使用的
改為 b+=b+2; 編譯器也會報錯。原因:out 型資料在方法中必須要賦值。
2). 過載方法時若兩個方法的區別僅限於一個引數型別為ref 另一個方法中為out,編譯器會報錯
eg:若將下面的程式碼中將方法名 vsum1 改為 sum(或者將方法名 sum 改為 sum1),編譯器會報錯。
Error 1 Cannot define overloaded method ‘sum’ because it differs from another method only on ref and out
原因:引數型別區別僅限於 為 ref 與為 out 時,若過載對編譯器而言兩者的後設資料表示完全相同。
class C
{
//1. in型引數
public void sum(int a, int b) {
a += b;
}
//2. ref型引數
public void sum(ref int a, int b)
{
a += b;
}
//3. out型引數
public void sum1(out int a, int b)
{
a = b+2;
}
public static void Main(string[] args)
{
C c = new C();
int a = 1, b = 2;
c.sum(a,b);
Console.WriteLine("a:{0}", a);
a = 1; b = 2;
c.sum(ref a, b);
Console.WriteLine("ref a:{0}", a);
a = 1; b = 2;
c.sum1(out a, b);
Console.WriteLine("out a:{0}", a);
}
}
輸出結果:
從程式碼也可以看出,int 型引數為值傳遞,所以當將變數 a 傳入方法時,變數 a 的值並不會發生變化。而 ref 型引數,由於是引用傳遞,將變數的值和地址都傳入方法中故變數值改變。out 型無法將變數的值傳入。但可以將變數的地址傳入併為該地址上的變數賦值。
按值傳遞引數的問題:
為什麼即使在函式內改變了值,值也沒有發生任何的變化呢?
在交換之前,a 的值:100
在交換之前,b 的值:200
在交換之後,a 的值:100
在交換之後,b 的值:200
1
2
3
4
解析:
呼叫一個方法時相當於複製一個物件到新分配的記憶體中,方法完畢物件也就del了,兩個變數是不同的兩個地址,a只不過是棧裡的臨時變數而已,和主函式裡的變數沒有關係,因此不會改變b的值。
而指標和引用直接訪問記憶體地址,故直接修改所指向的物件,兩者指向同一變數。
9、類的定義
定義一個類的時候相當於定義了一個資料型別的藍圖,本身沒有定義任何資料,但是它定義了類的名稱意味著什麼,就是說可以在這個類由什麼物件組成,以及在這個物件上可以執行什麼操作
累的定義
關鍵字 class 後跟類的名稱,類的主體包含在一段花括號中{},下面是類的一般形式
<access specifier> class class_name
{
// member variables
<access specifier> <data type> variable1;
<access specifier> <data type> variable2;
...
<access specifier> <data type> variableN;
// member methods
<access specifier> <return type> method1(parameter_list)
{
// method body
}
<access specifier> <return type> method2(parameter_list)
{
// method body
}
...
<access specifier> <return type> methodN(parameter_list)
{
// method body
}
}
請注意:
訪問識別符號 <access specifier> 指定了對類及其成員的訪問規則。如果沒有指定,則使用預設的訪問識別符號。類的預設訪問識別符號是 internal,成員的預設訪問識別符號是 private。
資料型別 <data type> 指定了變數的型別,返回型別 <return type> 指定了返回的方法返回的資料型別。
如果要訪問類的成員,你要使用點(.)運算子。
點運算子連結了物件的名稱和成員的名稱。
下面的例項說明了目前為止所討論的概念:
using System;
namespace BoxApplication
{
class Box
{
public double length; // 長度
public double breadth; // 寬度
public double height; // 高度
}
class Boxtester
{
static void Main(string[] args)
{
Box Box1 = new Box(); // 宣告 Box1,型別為 Box
Box Box2 = new Box(); // 宣告 Box2,型別為 Box
double volume = 0.0; // 體積
// Box1 詳述
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;
// Box2 詳述
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;
// Box1 的體積
volume = Box1.height * Box1.length * Box1.breadth;
Console.WriteLine("Box1 的體積: {0}", volume);
// Box2 的體積
volume = Box2.height * Box2.length * Box2.breadth;
Console.WriteLine("Box2 的體積: {0}", volume);
Console.ReadKey();
}
}
}
編譯執行後的結果:
Box1 的體積: 210
Box2 的體積: 1560
1
2
成員函式和封裝
類的成員函式是一個在類定義中有它的定義或原型的函式,就像其他變數一樣。作為類的一個成員,它能在類的任何物件上操作,且能訪問該物件的類的所有成員。
成員變數是物件的屬性(從設計角度),且它們保持私有來實現封裝。這些變數只能使用公共成員函式來訪問。
讓我們使用上面的概念來設定和獲取一個類中不同的類成員的值:
using System;
namespace BoxApplication
{
class Box
{
private double length; // 長度
private double breadth; // 寬度
private double height; // 高度
public void setLength( double len )
{
length = len;
}
public void setBreadth( double bre )
{
breadth = bre;
}
public void setHeight( double hei )
{
height = hei;
}
public double getVolume()
{
return length * breadth * height;
}
}
class Boxtester
{
static void Main(string[] args)
{
Box Box1 = new Box(); // 宣告 Box1,型別為 Box
Box Box2 = new Box(); // 宣告 Box2,型別為 Box
double volume; // 體積
// Box1 詳述
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// Box2 詳述
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
// Box1 的體積
volume = Box1.getVolume();
Console.WriteLine("Box1 的體積: {0}" ,volume);
// Box2 的體積
volume = Box2.getVolume();
Console.WriteLine("Box2 的體積: {0}", volume);
Console.ReadKey();
}
}
}
編譯執行後的結果:
Box1 的體積: 210
Box2 的體積: 1560
1
2
C# 中的建構函式
類的 建構函式 是類的一個特殊的成員函式,當建立類的新物件時執行。
建構函式的名稱與類的名稱完全相同,它沒有任何返回型別。
下面的例項說明了建構函式的概念:
using System;
namespace LineApplication
{
class Line
{
private double length; // 線條的長度
public Line()
{
Console.WriteLine("物件已建立");
}
public void setLength( double len )
{
length = len;
}
public double getLength()
{
return length;
}
static void Main(string[] args)
{
Line line = new Line();
// 設定線條長度
line.setLength(6.0);
Console.WriteLine("線條的長度: {0}", line.getLength());
Console.ReadKey();
}
}
}
編譯執行後的結果:
物件已建立
線條的長度: 6
1
2
預設的建構函式沒有任何引數。但是如果你需要一個帶有引數的建構函式可以有引數,這種建構函式叫做引數化建構函式。這種技術可以幫助你在建立物件的同時給物件賦初始值,具體請看下面例項:
using System;
namespace LineApplication
{
class Line
{
private double length; // 線條的長度
public Line(double len) // 引數化建構函式
{
Console.WriteLine("物件已建立,length = {0}", len);
length = len;
}
public void setLength( double len )
{
length = len;
}
public double getLength()
{
return length;
}
static void Main(string[] args)
{
Line line = new Line(10.0);
Console.WriteLine("線條的長度: {0}", line.getLength());
// 設定線條長度
line.setLength(6.0);
Console.WriteLine("線條的長度: {0}", line.getLength());
Console.ReadKey();
}
}
}
當上面的程式碼被編譯和執行時,它會產生下列結果:
物件已建立,length = 10
線條的長度: 10
線條的長度: 6
1
2
3
C# 中的解構函式
類的 解構函式 是類的一個特殊的成員函式,當類的物件超出範圍時執行。
解構函式的名稱是在類的名稱前加上一個波浪形(~)作為字首,它不返回值,也不帶任何引數。
解構函式用於在結束程式(比如關閉檔案、釋放記憶體等)之前釋放資源。解構函式不能繼承或過載。
下面的例項說明了解構函式的概念:
using System;
namespace LineApplication
{
class Line
{
private double length; // 線條的長度
public Line() // 建構函式
{
Console.WriteLine("物件已建立");
}
~Line() //解構函式
{
Console.WriteLine("物件已刪除");
}
public void setLength( double len )
{
length = len;
}
public double getLength()
{
return length;
}
static void Main(string[] args)
{
Line line = new Line();
// 設定線條長度
line.setLength(6.0);
Console.WriteLine("線條的長度: {0}", line.getLength());
}
}
}
當上面的程式碼被編譯和執行時,它會產生下列結果:
物件已建立
線條的長度: 6
物件已刪除
C# 類的靜態成員
我們可以使用 static 關鍵字把類成員定義為靜態的。當我們宣告一個類成員為靜態時,意味著無論有多少個類的物件被建立,只會有一個該靜態成員的副本。
關鍵字 static 意味著類中只有一個該成員的例項。靜態變數用於定義常量,因為它們的值可以通過直接呼叫類而不需要建立類的例項來獲取。靜態變數可在成員函式或類的定義外部進行初始化。你也可以在類的定義內部初始化靜態變數。
下面的例項演示了靜態變數的用法:
using System;
namespace StaticVarApplication
{
class StaticVar
{
public static int num;
public void count()
{
num++;
}
public int getNum()
{
return num;
}
}
class StaticTester
{
static void Main(string[] args)
{
StaticVar s1 = new StaticVar();
StaticVar s2 = new StaticVar();
s1.count();
s1.count();
s1.count();
s2.count();
s2.count();
s2.count();
Console.WriteLine("s1 的變數 num: {0}", s1.getNum());
Console.WriteLine("s2 的變數 num: {0}", s2.getNum());
Console.ReadKey();
}
}
}
編譯執行後的結果:
s1 的變數 num: 6
s2 的變數 num: 6
你也可以把一個成員函式宣告為 static。這樣的函式只能訪問靜態變數。靜態函式在物件被建立之前就已經存在。下面的例項演示了靜態函式的用法:
using System;
namespace StaticVarApplication
{
class StaticVar
{
public static int num;
public void count()
{
num++;
}
public static int getNum()
{
return num;
}
}
class StaticTester
{
static void Main(string[] args)
{
StaticVar s = new StaticVar();
s.count();
s.count();
s.count();
Console.WriteLine("變數 num: {0}", StaticVar.getNum());
Console.ReadKey();
}
}
}
編譯執行後的結果:
變數 num: 3
10、列舉型別:
列舉是一組命名整型常量。列舉型別是使用 enum 關鍵字宣告的。
C# 列舉是值型別。換句話說,列舉包含自己的值,且不能繼承或傳遞繼承。
- 宣告
語法
enum <enum_name>
{
enumeration list
};
1
2
3
4
enum RoleType{ //關鍵字+命名
apple, //物件,以逗號分隔
pen,
erase
}
RoleType rt = RoleType.apple; //使用列舉
其中,
enum_name 指定列舉的型別名稱。
enumeration list 是一個用逗號分隔的識別符號列表。
列舉列表中的每個符號代表一個整數值,一個比它前面的符號大的整數值。預設情況下,第一個列舉符號的值是 0.例如:
enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
例項:
下面的例項演示了列舉變數的用法:
using System;
namespace EnumApplication
{
class EnumProgram
{
enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
static void Main(string[] args)
{
int WeekdayStart = (int)Days.Mon;
int WeekdayEnd = (int)Days.Fri;
Console.WriteLine("Monday: {0}", WeekdayStart);
Console.WriteLine("Friday: {0}", WeekdayEnd);
Console.ReadKey();
}
}
}
編譯執行後的結果:
Monday: 1
Friday: 5
相關文章
- 初識C#網路程式設計C#程式設計
- 初級經典程式設計題程式設計
- 怎麼從初、中級Java程式設計師過渡到高階Java程式設計師?Java程式設計師
- 初級程式設計師的SQL拾遺-②(表操作)程式設計師SQL
- 如何從初級程式設計師變成高階程式設計師?程式設計師
- 初級程式設計師需要知道的基本程式碼規範程式設計師
- Epson機器人程式設計初級階(二)機器人程式設計
- 實驗 2 Scala 程式設計初級實踐程式設計
- 如何從初級程式設計師順利晉升到高階程式設計師?程式設計師
- [譯] 我在程式設計初級階段常犯的錯誤程式設計
- 初級Java程式設計師提升自己的3條路線Java程式設計師
- 初級程式設計師的SQL拾遺(增刪改查)程式設計師SQL
- c#程式設計C#程式設計
- 看看這個常常被初級程式設計師弄不懂的 “事件”程式設計師事件
- C#中的函數語言程式設計:序言(一)C#函數程式設計
- 初識shell程式設計程式設計
- 初級Java程式設計師職業規劃如何選擇Java程式設計師
- Matlab圖形使用者介面程式設計初級入門Matlab程式設計
- 初試python的socket程式設計--ftpPython程式設計FTP
- 一文說通C#中的非同步程式設計C#非同步程式設計
- C#非同步程式設計C#非同步程式設計
- C# 管道式程式設計C#程式設計
- C# 併發程式設計C#程式設計
- C# 非同步程式設計C#非同步程式設計
- 網路程式設計初學程式設計
- C#並行程式設計:Parallel的使用C#並行行程程式設計Parallel
- [03] C# Alloc Free程式設計C#程式設計
- C# .NET網路程式設計C#程式設計
- c# 程式設計學習(四)C#程式設計
- c# 程式設計學習(二)C#程式設計
- C#程式設計學習(一)C#程式設計
- Python GUI介面程式設計-初識PythonGUI程式設計
- 一文說通C#中的非同步程式設計補遺C#非同步程式設計
- 中國的頂級軟體程式設計工程師和歐美的頂級軟體程式設計工程師差距有多大?程式設計工程師
- 服務端指南 | 微服務初級設計指南服務端微服務
- C# - 非同步程式設計 - BackgroundWorker 類C#非同步程式設計
- 初見函數語言程式設計函數程式設計
- 簡單探討C#中GUI程式設計的標準事件問題C#GUI程式設計事件