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
相關文章
- 初級JAVA程式設計師的困惑Java程式設計師
- 初識C#網路程式設計C#程式設計
- 怎麼從初、中級Java程式設計師過渡到高階Java程式設計師?Java程式設計師
- 初級程式設計師的SQL拾遺-②(表操作)程式設計師SQL
- 如何從初級程式設計師變成高階程式設計師?程式設計師
- 初級程式設計師考試大綱 (轉)程式設計師
- 實驗 2 Scala 程式設計初級實踐程式設計
- 初級程式設計師需要知道的基本程式碼規範程式設計師
- 如何從初級程式設計師順利晉升到高階程式設計師?程式設計師
- 面試中初級程式設計師常常遇到的問題—— 描述你做過的專案面試程式設計師
- 初級Java程式設計師提升自己的3條路線Java程式設計師
- 初級程式設計師的SQL拾遺(增刪改查)程式設計師SQL
- [譯] 我在程式設計初級階段常犯的錯誤程式設計
- [轉載]初級Java程式設計師的學習路線Java程式設計師
- 初級程式設計師應該瞭解的Linux命令程式設計師Linux
- 看看這個常常被初級程式設計師弄不懂的 “事件”程式設計師事件
- 初級Java程式設計師所面臨的4大挑戰Java程式設計師
- 招聘初級程式設計師必須考慮的6個因素程式設計師
- Epson機器人程式設計初級階(二)機器人程式設計
- c#程式設計C#程式設計
- 初學者的程式設計自學指南程式設計
- 初識shell程式設計程式設計
- C#中的函數語言程式設計:序言(一)C#函數程式設計
- C#~非同步程式設計在專案中的使用C#非同步程式設計
- 淺析C#程式設計中的記憶體管理C#程式設計記憶體
- 初級Java程式設計師職業規劃如何選擇Java程式設計師
- 初學者學習程式設計的方法程式設計
- 一文說通C#中的非同步程式設計C#非同步程式設計
- 【程式人生】程式設計初學者的良言警句(轉)程式設計
- 網路程式設計初學程式設計
- Matlab圖形使用者介面程式設計初級入門Matlab程式設計
- Java進階之路——從初級程式設計師到架構師Java程式設計師架構
- 微軟將推新程式語言M#:系統程式設計級別的C#微軟程式設計C#
- c# 實現初級的語音識別C#
- 30 歲轉行做初級程式設計師是什麼樣的體驗程式設計師
- Java GUI程式設計之圖片分攤小工具的實現(初級)JavaGUI程式設計
- 初試python的socket程式設計--ftpPython程式設計FTP
- C# 4.0中的動態型別和動態程式設計C#型別程式設計