本教程參考C#和ASP.NET程式設計教程撰寫,有什麼不足之處請大家指出,或在老貓的理想BLOG留言。
首先講解一下c#,這裡只是粗略的講解,詳細內容請購買相關書籍,或參閱相關文檔。c#已經取消了c++中的指標,並且在c++中大量被使用的操作符(:: ->)已經不在出現,c#中指支援一個"."。c#具有物件導向程式設計語言的所有特性,如封裝、繼承、多態等。而且比java更物件導向,每種類型都可以看作一個對象。但c#指允許單繼承,即一個類不會有多個基類。另外,c#沒有了全域函數,沒有了全域變數,也沒有了全域常量。一切都必須封裝在一個類中。
下面舉一個控制台應用程式的小例子:
using System;
class MikeCat
{
public static void Main()
{
Console.WriteLine("邁克老貓c# asp.net入門系列教程--歡迎訪問老貓的理想");
}
}
在c#中程式總是從Main()方法開始,Main()方法必須且只能包含在一個類中,Main()方法返回的類型可以是void(無傳回值)或int(返回代表應用程式錯誤層級的整數)。
上面的using System;用於匯入名字空間(Namespace)用來表明類的層次關係。如果不用using匯入名字空間,則每次用某一個類時就得在類名前面加上名字空間。
c#程式的輸入輸出通過Console來實現。Console是System名字空間下的一個類。在螢幕上輸出一個字串用Console.WriteLine(),接受輸入裝置的輸入用Console.ReadLine()方法。
程式碼:
class MikeCat
{
public static void Main()
{
System.Console.WriteLine("邁克老貓c# asp.net入門系列教程--歡迎訪問老貓的理想"n");
System.Console.WriteLine("請輸入使用者名稱:");
string user=System.Console.ReadLine();
System.Console.WriteLine("歡迎你:{0}的光臨!",user);
}
}
WriteLine()方法的參數表中緊隨串後的第一個參數將替換{0}。
如果執行程式時要傳遞命令列參數給應用程式,則Main()方法的格式應為:
using System;
public class MikeCat
{
public static void Main(string[] args)
{
Console.WriteLine("共有{0}個命令列參數",args.Length);
for(int i=0;i<args.Length;i++)
{
Console.WriteLine("Arg[{0}]=[{1}]",i,args[i]);
}
}
}
c#中的單行注釋用//,多行注釋用/*...*/
c#中使用常量:
using System
class MikeCat
{
public const double PI=3.14;
public static void Main()
{
Console.WriteLine("圓周率PI的值為{0}",PI);
}
}
結構體類型(struct)是一種複合資料型別,用於將某些相關的資料群組織到一個新的資料類型中。
using System;
struct MikeCat
{
public string Mike;//user
public uint Age;//age
public string Email;//email
}
class mf
{
public static void Main()
{
MikeCat zl;//聲明結構體類型變數zl
zl.Name="邁克老貓";
zl.Age=24;
zl.Email="mike@hebut.com";
Console.WriteLine("姓名:{0},年齡:{1},郵箱:{2}",zl.Name,zl.Age,zl.Email);
}
}
c#中枚舉類型(enum)是一組邏輯上密不可分的整數值:
using System;
enum WeekDay
{
Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday
};//注意這裡的分號
class MikeCat
{
static void Main()
{
WeekDay day;//聲明枚舉型變數day
day=WeekDay.Tuesday;
Console.WriteLine("day的值是{0}",day);
}
}
c#中枚舉類型中的每個元素類型均為int byte long short型,且第一個元素值為0,其後面的按1遞增。在枚舉中也可以直接給元素賦值,後面的遞增。
enum WeekDay:byte
{
Sunday=1,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday
};
繼續上回,數組是我們經常用到的,我來介紹一下:數組是具有相同類型的一組資料。當訪問數組中的資料時,可以通過下標來指明。c#中數組元素可以為任何資料類型,數組下標從0開始,即第一個元素對應的下標為0,以後逐個遞增。數組可以一維也可多維。
//包含6個元素的一維整數數組;
int[] mf1=new int[6]; //注意初始化數組的範圍,或者指定初值;
//包含6個元素的一維整數數組,初值1,2,3,4,5,6
int[] mf2=new int[6](1,2,3,4,5,6);
//一維字串數組,如果提供了初始值設定項,則還可以省略 new 運算子
string[] mf3={"c","c++","c#"};
//一維對象數組
Object[] mf4 = new Object[5] { 26, 27, 28, 29, 30 };
//二維整數數組,初值mf5[0,0]=1,mf5[0,1]=2,mf5[1,0]=3,mf5[1,1]=4
int[,] mf5=new int[,]{{1,2},{3,4}};
//6*6的二維整型數組
int[,] mf6=new mf[6,6];
下面來看一個一維字串數組的遍曆
using System;
public class MikeCat
{
static void PrintArray(string[] arr)
{
//列印數組元素,arr.Length 表示數組元素的個數
for(int i=0;i<arr.Length;i++)
{
Console.WriteLine("arr[{0}]={1}",i,arr[i]);
}
}
public static void Main()
{
string[] arr={"c","c++","c#"};
//將數組作為一個參數傳遞
PrintArray(arr);
}
}
程式結果:arr[0]=c arr[1]=c++ arr[2]=c#
下面來看一個4行2列(4*2)的整型數組的遍曆:
using System;
public class MikeCat
{
static void PrintArray(int[,] arr)
{
//通過兩次FOR迴圈遍曆二維數組
for(int i=0;i<4;i++)//初始化i作為迴圈變數,i++實現該變數的自增運算。
//for迴圈滿足條件後執行完迴圈體一次後執行i++,然後進入下次迴圈。簡單的c文法,這裡做簡單介紹照顧初學者。(詳細可參閱譚浩強先生的c語言程式設計一書)
{
for(int j=0;j<2;j++)
{
Console.WriteLine("arr[{0},{1}]={2}",i,j,arr[i,j]);//列印每個二維數組元素
}
}
}
public static void Main()
{
//主函數
//將數組作為一個參數傳遞
PrintArray(new int[,]{{1,2},{3,4},{5,6},{7,8}};
}
}
運行結果:arr[0,0]=1 arr[0,1]=2 arr[1,0]=3 arr[1,1]=4 arr[2,0]=5 arr[2,1]=6 arr[3,0]=7 arr[3,1]=8
類是物件導向程式設計的基本構造塊,詳細我們在後面介紹。這裡我們介紹兩個特殊的類,即object類和string類
1.object類
object類是預定義類System.Object的別名,它是所有其他類型的基類。c#中所有類型都直接或間接從object類中繼承。因此,一個object類的變數可以賦予任何類型的值。
int i=30;
object obj1;
obj1=i;
object obj2='a';
2.string類
string類專門用於對字串的操作,他是預定義類System.String的別名
string str1="mikecat";
可以用"+"號串連兩個字串。
string str2="username:"+"mikecat";
如果訪問單個字元,則要用下標。
char c=str1[0];
比較兩個字串是否相等,可用比較操作符"=="//有別於basic文法
bool b=(str1==str2);
c#中,取消了c和c++中使用最靈活,也是最難掌握的指標。那麼在c#中如何提供c/c++中的函數指標的功能?c#提供了委託(delegate),委託是繼承自System.Delegate類的參考型別。它相當於函數指標原型。與函數指標不同的是,委託在c#中是型別安全的,委託特別適合於匿名調用。要使用委託需經過三個步驟,即聲明、執行個體化、調用。
using System;
//聲明一個名為mfDelegate的委託,該委託有一個string類型的參數
//c#編譯器編譯時間會產生一個新類,該類繼承自System.Delegate,類
//名為mfDelegate
public delegate void mfDelegate(string name);
public class MikeCat
{
//定義與mfDelegate有相同參數類型的方法Hello()
public static void Hello(string name)
{
Console.WriteLine("您好,{0}!",name);
}
//定義與mfDelegate有相同參數類型的方法GoodBye()
public static void GoodBye(string name)
{
Console.WriteLine("再見,{0}!",name);
}
public static void Main()
{
//建立一個mfDelegate執行個體 mf1
mfDelegate mf1=new mfDelegate(Hello);
//調用mf1
mf1("mikecat");
mfDelegate mf2=new mfDelegate(GoodBye);
mf2("mikecat");
//將mf1 mf2組合成一個新的委託mf3
mfDelegate mf3=mf1+mf2;
//調用mf3
mf3("邁克老貓");
//從組合的委託mf3中刪除mf1
mfDelegate mf4=mf3-mf1;
mf4("mikecat");
}
}
程式結果:您好,mikecat!//mf1; 再見,mikecat!//mf2
您好,邁克老貓! 再見,邁克老貓!//mf3
再見,mikecat!//mf4
這次我們首先講解一下類型轉換,我們在寫程式時經常用到類型轉換,而且特別多的規則。我在這裡粗略的講解一下。
隱式轉換是系統預設的、不需要加以聲明即可進行的轉換。
1.隱式數值轉換
隱式數值轉換實際上就是從低精度的數實值型別轉換到高精度的數實值型別的轉換。
byte x=255;ushort y=x;y=65535;float z=y;//均從低精度到高精度,反之會產生溢出
隱式數值轉換的類型太多,我就不多介紹,記住上面的原則就可以了。詳細規則可查看msdn
2.隱式枚舉轉換
隱式枚舉轉換用於把十進位整數0轉換成任何枚舉類型,對應的其他整數則不存在這種轉換。
using System;
enum Color
{
Red,Green,Blue
};
class MikeCat
{
static void Main()
{
Color c;//聲明Color的變數c;
c=0;//將0轉換為Red;
Console.WriteLine("c的值是{0}",c);//結果:c的值是Red;如果將c=0改成c=1,則編譯器會給出錯誤。
}
}
3.隱式引用轉換
從任何參考型別到object的轉換。
從類類型A到類類型B的轉換,其中類A從類B派生得到。
從類類型A到介面類型B的轉換,其中類A實現了介面B。
從介面類型A到介面類型B的轉換,其中介面A是從介面B派生。
從任何數群組類型到System.Array的轉換。
從任何委託類型到System.Delegate的轉換。
從任何數群組類型或委託類型到System.ICloneable的轉換。
從空類型(null)到任何參考型別的轉換。
顯示轉換也稱為強制轉換,它需要使用者明確地指定轉換的類型。
char c=(char)65;//A
int i=(int)'A';//65
顯示轉換包含所有的隱式轉換,即任何系統允許的隱式轉換寫成顯示轉換的形式都是允許的。
int i=300;
long l=(long)i;
另外一例:
using System;
class MikeCat
{
static void Main()
{
long longValue = Int64.MaxValue;
int intValue = (int) longValue;
Console.WriteLine("(int){0} = {1}", longValue, intValue);
}
}
類型 long 轉換為 int 是顯式轉換,它使用了強制轉換運算式。輸出為:
(int) 9223372036854775807 = -1這是因為有溢出發生。
1.顯示數值轉換
顯示數值轉換是指當不存在相應的隱式轉換時從一種數實值型別轉換為另一種數實值型別。轉換類型也很繁瑣,只需記住轉換規則,詳細查閱MSDN。由於顯示數值轉換可能丟失資訊或引發異常,因此轉換按以下原理被處理:簡略說就是高精度顯示轉換為低精度會引發異常(OverFlowException),未引發異常的情況,源變數的值通過舍入得到最接近的整型值作為轉換結果。詳細轉換時的異常情況查閱MSDN
/*test.cs*/
using System;
public class MikeCat
{
public static void Main()
{
ushort u=65535;
byte b=(byte)u;
Console.WriteLine("b的值是{0}",b);
}
}
編譯狀況如下:
E:">csc test.cs
Microsoft (R) Visual C# .NET 編譯器版本 7.10.3052.4
用於 Microsoft (R) .NET Framework 版本 1.1.4322
著作權 (C) Microsoft Corporation 2001-2002。著作權所有,並保留一切權利。
E:">test.exe
b的值是255
E:">csc/checked test.cs ///checked[+|-] 產生溢出檢查
E:">test.exe
未處理的異常: System.OverflowException: 算術運算導致溢出。
at MikeCat.Main()
E:">csc/checked- test.cs
E:">test.exe
b的值是255
2.顯示枚舉轉換
顯示枚舉轉換其實就是將枚舉類型的元素類型與相應類型之間進行隱式顯示轉換。比如,有一個元素類型int的枚舉類型E,當執行從E到byte的顯示枚舉轉換時,實際執行的是從int到byte的顯示數值轉換。
using System;
enum Color
{
Red,Green,Blue
};
public class MikeCat
{
static void Main()
{
Color c;//聲明Color的變數c;
c=(Color)4;//對數字3進行顯示枚舉轉換
Console.WriteLine("c的值是{0}",c);
}
}
結果:c的值是4
Convert 類
將一個基礎資料型別 (Elementary Data Type)轉換為另一個基礎資料型別 (Elementary Data Type)。
該類傳回值與指定類型的值等效的類型。受支援的基底類型是 Boolean、Char、SByte、Byte、Int16、Int32、Int64、UInt16、UInt32、UInt64、Single、Double、Decimal、DateTime 和 String。
存在將每個基底類型轉換為每個其他基底類型的轉換方法。不過,所執行的實際轉換操作分為三類:
從某類型到它本身的轉換隻返回該類型。不實際執行任何轉換。
無法產生有意義的結果的轉換引發 InvalidCastException。不實際執行任何轉換。下列轉換會引發異常:從 Char 轉換為 Boolean、Single、Double、Decimal 或 DateTime,以及從這些類型轉換為 Char。下列轉換會引發異常:從 DateTime 轉換為除 String 之外的任何類型,以及從任何類型(String 除外)轉換為 DateTime。
任何基底類型(上面描述的基底類型除外)都可以與任何其他基底類型進行相互轉換。
如果數字類型轉換導致精度丟失(即某些最低有效位丟失),不引發異常。但是,如果結果超出了特定轉換方法的傳回值類型所能表示的範圍,則將引發異常。
下面介紹一下和類型轉換相關的裝箱、unboxing
裝箱是實值型別到 object 類型或到該實值型別所實現的任何介面類型的隱式轉換。將一個值的值裝箱會分配一個對象執行個體並將該值複製到新的對象中。
請看以下實值型別變數的聲明:
int i = 123;
以下語句對變數 i 隱式應用裝箱操作:
object o = i;
此語句的結果是在堆棧上建立對象 o,而該對象在堆上引用 int 類型的值。該值是賦給變數 i 的實值型別值的一個副本。說明了兩個變數 i 和 o 之間的差異。
裝箱轉換
在堆棧上 在堆上
i 123
int i=123;
o (將i裝箱)
object o=i; int 123
也可以(但絕不必要)如下例所示顯式執行裝箱:
int i = 123;
object o = (object) i;
樣本
此例將整數變數 i 通過裝箱轉換為對象 o。這樣,儲存在變數 i 中的值就從 123 更改為 456。此例顯示對象保留了內容的原始副本,即 123。
// boxing.cs
// Boxing an integer variable
using System;
class TestBoxing
{
public static void Main()
{
int i = 123;
object o = i; // Implicit boxing
i = 456; // Change the contents of i
Console.WriteLine("The value-type value = {0}", i);
Console.WriteLine("The object-type value = {0}", o);
}
}
輸出
The value-type value = 456
The object-type value = 123
unboxing
unboxing是從 object 類型到實值型別或從介面類型到實現該介面的實值型別的顯式轉換。unboxing操作包括:
檢查對象執行個體,確保它是給定實值型別的一個裝箱值。
將該值從執行個體複製到實值型別變數中。
以下語句同時說明了裝箱和unboxing操作:
int i = 123; // A value type
object box = i; // Boxing
int j = (int)box; // Unboxing
顯示了以上語句的結果。
unboxing轉換
在堆棧上 在堆上
i 123
int i=123;
o (將i裝箱)
object o=i; int 123
j 123
int j=(int) o;
為使到給定實值型別的unboxing轉換在運行時取得成功,源參數的值必須是對某個對象的引用,而該對象先前是通過將該實值型別的值裝箱建立的。如果源參數為 null 或是對一個不相容對象的引用,則會引發 InvalidCastException。
樣本
下面的樣本闡釋無效unboxing的情況,即錯誤的unboxing如何導致 InvalidCastException。通過使用 try 和 catch,發生錯誤時會顯示錯誤資訊。
using System;
public class UnboxingTest
{
public static void Main()
{
int intI = 123;
// Boxing
object o = intI;
// Reference to incompatible object produces InvalidCastException
try
{
int intJ = (short) o;
Console.WriteLine("Unboxing OK.");
}
catch (InvalidCastException e)
{
Console.WriteLine("{0} Error: Incorrect unboxing.",e);
}
}
}
輸出
System.InvalidCastException
at UnboxingTest.Main() Error: Incorrect unboxing.
如果將下列語句:
int intJ = (short) o;
更改為:
int intJ = (int) o;
轉換將執行,而您將得到輸出“Unboxing OK”。