C++程序員光速入門C#(一):總覽、數據類型、運算符
一.Hello world!
隨著.NET的深入人心,作為一個程序員,當然不能在新技術面前停而止步,面對著c++在.net中的失敗,雖然有一絲遺憾,但是我們應該認識到,對于c++其實就不應該對其在.Net中的表現有太大的奢望,因為畢竟它并不是一個.Net下的正統語言,.Net應該是c#的舞臺,作為一個c++程序員,我們應該慶幸,因為我們學習c#其實是簡單的直接的,需要我們接受的新知識其實不多。相對其他語言來說,我們應該可以更加平滑的過渡到c#的開發中.廢話不多說,現在就讓我們用c++的基礎來學習這個漸漸壯大的新語言-----C#。
對于C#的講解我只講解和C++有區別的地方,相同的部分我就一帶而過,這樣的對比學習可以讓我們在已有知識的前提下快速掌握C#。
一開始學習語言大部分的教程都會用一個Hello World程序來示范,我們也落入俗套,用Hello World來和C++中做一個比較。
/******************C++程序**********************/
#include <iostream>
using namespace std;
int main()
{ //C++程序 cout<<"Hello World!"<<endl; return 0;
}
/********************C#程序*********************/
using System;
namespace HelloWorld
{ class Class1 { //C#程序 static void Main() { Console.WriteLine ("Hello World!"); } }
}
乍一眼看上去兩者差不多,心中一陣竊喜,可以說C#對語法的定義更加嚴格一些。
首先對于程序的進入點,最大的區別就是Main函數的開頭必須要大寫。因為C#是一個完全面向對象的程序語言,所以它的所有代碼都必須定義在一個類中,Main函數也不例外。同時因為.net程序在編譯運行時都是先轉為中間語言,然后中間語言再編譯為機器語言,這樣的好處有2個。一,如同Java一樣,寫好的程序可以在不同的系統中運行,而不需要改變程序;二,使用不同的語言寫的程序,因為要轉化為相同的中間語言,所以在程序開發中可以使用不同的程序語言編寫,而相互調用。
當使用不同語言開發或者進行分類開發時,各自開發的程序中會出現相同的變量名,函數名等,所以在寫C#程序時,必須把程序包涵在一個名字空間內。C++在多文件編程的時候出現重復的變量名的時候,會比較頭疼,C#則沒有這個問題,因為所有的類定義都要在一個命名空間里,而變量只能定義在類中,不存在所謂的全局變量。
定義名字空間使用關鍵字:namespace <空間名>,當一個命名空間中的代碼需要使用在另一個名字空間中定義的名稱,就必須包括對該命名空間的引用,使用點字符(.) 。
/********************C#程序*********************/
namespace HelloWorld
{class Program{static void Main(string[] args){LevelOne.A a1 = new LevelOne.A();a1.a = 10086;LevelOne.LevelTwo.A a2 = new LevelOne.LevelTwo.A();a2.a = 10086;}}namespace LevelOne{class A{public int a;}namespace LevelTwo{class A{public int a;}}}
}
這里就定義了兩個名字相同的變量,我們可以使用LevelOne.A 和 LevelOne.LevelTwo.A 來獨立創建兩個對象,它們互不干擾。建立了名字空間后,我們可以使用using關鍵字來簡化對它們包含的名稱的訪問。和C++中使用using namespace std的含義相似。
對于主函數必須要有限定詞static 這表明Main函數是靜態的,在內存中只能有一個副本。
第一行中的using System.其命名空間是.NET應用程序的根名字空間,包涵了控制臺應用程序所需要的所以基本功能。就如同C++中的頭文件包涵在std這個名字空間中一樣。
Console.WriteLine ("Hello World!");
Console是system名字空間中的一個類,其有一個WriteLine方法,它的作用和cout一樣,輸出一行字符串。
二.數據類型
C#中的數據類型和C++是類似的。
1.浮點類型
浮點類型中添加了一個精度更高的_decimal_類型,對于金融方面的程序開發,此種數據類型用來定義錢幣.
2.bool類型
_bool_類型的變量只能賦值為false和true。雖然它們的含義仍然是0和非0,但是在使用中不能再給它們賦值成整數值,在判斷語句中 if (bool a==1) 的使用都是錯誤的。這樣的語法讓bool類型的意義更加準確。
3.字符類型
_char_類型在C#中是16位的,它不能接收一個整數值,這與C++有所不同。
4.整數類型
整數類新中添加了_byte_(8位無符號整數),sbyte(8位有符號整數),short(16位有符號整數) 類型
_long_變成了真正的64位有符號整數,它可以用在64位機器的編程中。
uint,ushort,ulong_顧名思義是沒有符號的整數,它類似于C++中的_unsigned int,名字換了一下而已。
_long_類型在C++中的大小是根據編譯器位數改變的,32位編譯器的時候是4字節,跟_int_沒區別。而64位的時候才是8字節,坑爹!
5.字符串類型
string類型是字符串類型,它是引用的類型,它的使用方法和C++中string的使用相似,可以進行+運算(運算符重載)。
string類型有一些方法可以給我們使用,類似C++。例如:ToCharArray() 把字符串放入一個字符數組中等等,可以在MSDN中查找。
6.類型的轉換
C#是一個強類型的語言,它的數值類型有一些可以進行隱式轉換,其他的必須顯式轉換,隱式轉換的類型只能是長度短的類型轉換成長的類型,例如_int_可以轉換成_long_,float,double,_decima_l。反之必須顯式的轉換。
int a=7;
float b=a; //隱式轉換
long c=12L; //和C++一樣必須加上后綴L才能將一個常量定義為long型
a=(int)c; //顯式轉換
使用上面的顯示轉換不能用在bool和string類型上,如果希望string或者bool類型和整數類型之間的轉化可以使用一個方法:
//Convert.To*****(val)
//*****:一種數據類型(具體請參看MSDN) val:可以是這種類型的變量
int a=123;
string str=Convert.ToString(a);
bool m_bool=Convert.ToBoolean(a);
7.枚舉類型
C++和C#的枚舉類型,定義相同,使用也相同,只要注意C#中語句最后不需要;結束符。同時定義枚舉類型時也不許放在主函數代碼段中它只能放在執行代碼外面,如下
using System;
namespace HelloWorld
{class Program{enum Week{ monday=5, tuesday, wednesday,thursday, friday, saturday,sunday }static void Main(string[] args){int a = (int)Week.tuesday;//輸出數字6,Right?Console.WriteLine(a);Console.ReadKey();}}
}
8.指針類型
c++中奉為經典的指針類型,在C#中已經取消了,真不知道這個是一個好消息還是壞消息,不過在易用性方面來說因該是一個進步。不過c#中其實在隱藏了一個指針,我們會在后面說到,同時在C#中也可以包含不安全代碼,這些代碼就是使用了指針的代碼。
9.結構類型
C#中的結構類型看上去和C++沒有什么區別,定義使用也相似,但還有有很大的區別的,首先就和枚舉類型相似, 最后不需要;結束符,同時定義時也不許放在主函數代碼段中它只能放在執行代碼外面。其二最大的區別就是C#中的結構已經和類相似了,不同的地方在于:C++中的結構中成員變量是公有的,而C#中是私有的,C#中的結構和類的區別唯一就是不能繼承(但是可以有接口,這個以后會講到),但是C#結構是在堆棧中創建的空間,所以最好是對小量的數據進行操作。
/**********************C#程序************************/
using System;
namespace HelloWorld
{class Program{public struct Student{public int intVar;public double doubVar;}static void Main(string[] args){Student a, b;a.intVar = 1;a.doubVar = 1.1;b = a;a.doubVar = 2.6;Console.WriteLine("{0} {1} {2} {3}", b.doubVar, b.intVar, a.intVar, a.doubVar);Console.WriteLine("{1} {0} {3} {2}", b.doubVar, b.intVar, a.intVar, a.doubVar);}}
}/*********************************
輸出結果: 1.1 1 1 2.6 1 1.1 2.6 1
**********************************//*******************************//C#中的結構類型不能繼承!struct A{ }//ERROR!!struct B:A{}class C{ }//YES!class D : C{}
********************************/
C#中的輸出定位格式和C語言中的printf類似,但更加簡潔,不需要在對不同類型的變量使用不同的占位符,只需對應后面跟著的變量,給出序號就可以了。
10.數組類型
數組的定義和C++有區別,看上去很別扭,定義語法為:
<類型>[] <變量名> 例: int[] num;
這樣就定義了一個int類型的數組,但是切記它可和C++不同,[]里面可不要寫內容哦!int[10] num可是錯誤的。確定數組的大小有兩個辦法:
一,在定義時指定數據
int[] num = {5,3,7,3};
二,使用關鍵字new,例:
int[] num = new int[4];
當然兩者也可以合起來,例:
int[] num = new int[4]{5,3,7,3};
注意:前面定義了4個數據,后面花括號里面就必須有4個數據,不然就是錯誤的。
//錯誤!!
//int [] num = new int[4]{4,3};
并且,對多維數組的定義和C++是不同的。C++中定義為
int num[3][4] = {1,2,3,4,5,3,2,3,4,2,3,4};
C#中定義為
int[,] num = new int[3,4]{{1,2,3,4},{5,3,2,3},{4,2,3,4}};
注意,和C++不同C#不能在數據列表中不分類,也就是說不使用{}把一組括起來是錯誤的,而在C++中是正確的。
//ERROR to C#!!!
//int[,] num=new int[3,4]{1,2,3,4,5,3,2,3,4,2,3,4};
對數據的使用和賦值也相應的變為
//C#的數組成員使用和賦值
num[2,1]=3;
//C++的數組成員使用和賦值
num[2][1]=3;
C#在數組中最富革命性的改變,應該就是是添加了鋸齒形數組(或者說交錯數組)。例如它可以添加一組{{1,2,3,4},{2,3},{2,3,1}}長度不一樣的數據,,在C++中只能創建一個三行四列的數組,在C#中它能夠產生這樣一個鋸齒形數組,第一組中有4個數據,第二組中有2個數組,第三組中有3個,這樣可以不浪費內存。
靈魂繪圖
鋸齒數組的定義和前面的定義也有區別,它更像是一個數組中包含了一個數組
int[][] num = new int[3][];
num[0] = new int[4]{1,2,3,4};
num[1] = new int[2]{2,3};
num[2] = new int[3]{2,3,1};
下面是上面的定義的一種簡潔寫法:
int[][] sum = {new int[]{1,2,3,4}, new int[]{2,3}, new int[]{2,3,1}};
三.變量
變量的使用和作用域和C++類似,沒有什么特別需要注意的。但是首先我們應該看到,C#是一門完全面向對象的語言,也就是說定義的變量都變成了類的私有成員(定義時如果沒加訪問修飾符的話)。如果要在別的類中使用變量就需要在定義語句前加上訪問修飾符public。
在C#中必須給每個變量添加訪問修飾符
public int a;
public int b;
C#中的訪問修飾符還有一些,如下:
internal:變量只能在當前程序中使用.
new:在用作修飾符時,new 關鍵字可以顯式隱藏從基類繼承的成員。
private:私有的,和C++中含義一樣
protected:保護類型,和C++中含義一樣
static:靜態的,和C++中含義一樣
readonly: 只讀,在變量初始化(構造函數)以后就不許改變.
protected internal:雙重限定,但只有這一個組合
訪問修飾符_new_的用法如下
public class Program : BaseClass
{new public class Test//2、new修飾符 顯式隱藏從基類繼承的成員{public int x = 2;public int y = 20;public int z = 40;}static void Main(string[] args){var c1 = new Test();//1、new操作符 創建對象和調用構造函數var c2 = new BaseClass.Test();Console.WriteLine(c1.x);//2Console.WriteLine(c2.y);//10Console.ReadKey();}
}public class BaseClass
{public class Test{public int x = 0;public int y = 10;}
}
四.常量
C#有兩種常量,一種是_const_修飾的,一種是_readonly_修飾的。
_const_和_readonly_的區別是:
1._readonly_為運行時常量,程序運行時進行賦值,賦值完成后便無法更改,因此也有人稱其為只讀變量。_const_為編譯時常量,程序編譯時將對常量值進行解析,并將所有常量引用替換為相應值。
2._readonly_常量只能聲明為類字段(即C++中的成員變量),支持實例類型或靜態類型,可以在聲明的同時初始化或者在構造函數中進行初始化,初始化完成后便無法更改。_const_常量除了可以聲明為類字段之外,還可以聲明為方法中的局部常量,默認為靜態類型(無需用_static_修飾,否則將導致編譯錯誤),但必須在聲明的同時完成初始化。
static void Main(string[] args)
{//OKconst int a = 10;//ERROR!!//readonly int b = 10;
}
3.由于_const_常量在編譯時將被替換為字面量,使得其取值類型受到了一定限制。_const_常量只能被賦予數字(整數、浮點數)、字符串以及枚舉類型。而_readonly_則可以修飾類對象。
//ERROR!!
//public const DateTime D = DateTime.MinValue;
//OK
public readonly DateTime D = DateTime.MinValue;
五.運算符
C#中的運算符,優先級和C++一樣,但是需要注意下面的四個運算符
* , -> , & ,sizeof
上面的四個運算符在C#的不安全代碼中可以使用,但在一般的C#代碼中使用是錯誤的,C#取消了指針,當然和指針有關的操作符都不能用了。