一個demo學會c#
阿新 • • 發佈:2018-12-26
全棧工程師開發手冊 (作者:欒鵬)
學習了c#4.5高階程式設計這本書,自己喜歡邊學邊總結邊寫demo,所以寫了這篇文章,包含了大部分的c#程式設計知識。讓你一個demo掌握c#程式設計,如果有問題可以留言。
此demo主要包括五個檔案:Students.cs和Moniter.cs檔案,包含了自定義空間、空間函式、空間變數、空間自定義類;Interface1.cs檔案和Interface2.cs檔案為介面檔案;index.cs檔案為主程式運算。
Students.cs和Moniter.cs檔案包含了自定義基、繼承類、模板類的定義及實現。涉及到自定義類的建構函式、過載建構函式、函式預設值、解構函式、複製建構函式、過載運算子(賦值函式、加法函式)、虛擬函式、常值函式、靜態函式、靜態變數、常值變數、列舉變數、內部類、訪問修飾符、繼承、重寫虛擬函式、基類引用、不定引數函式、友函式、友類、型別引用、終態函式、終態類、模板變數等內容。
Students.cs檔案內容如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace csharpdemo
{
//自定義結構體,值型別
struct People
{
string name;
int id;
}
//static int vartemp=10; //禁止使用脫離類的全域性資料
//自定義類,引用型別。一個檔案可以包含多個類,類預設為修飾符為私有
public class Student : IComparable<Student>
{
public static void main(String[] args) { } //每個類中都可以有一個main函式,用於除錯
static Student() { default_name = "student"; } //靜態建構函式,在第一次呼叫類的任何成員之前,僅執行一次,不能有引數,不用訪問修飾符,且只有有一個
public Student() //自定義無參構造器,沒有自定義構造器時,編譯器會生成預設無參構造器,
: this("student", 12) //通過this僅能呼叫一個構造器,必須將構造器呼叫置於起始處
{
getname();
Console.WriteLine("基類無參構造器建立了一個物件");
}
public Student(string name,int age){ //有參構造器,設定int age=12為預設值,可單引數呼叫
this.age = age; this.name = name;
Console.WriteLine("基類有參構造器建立了一個物件");
}
public Student(string name,params object[] args) //可變引數列表,args是一個引數列表,過載方法中應該只有一個使用可變引數列表,且位於引數的最後面,編譯器會自動呼叫最符合的過載函式執行
{
this.name = name; Console.WriteLine("基類變參構造器開闢了一個物件"); //args[0]為變參中的第一個引數
}
~Student() { Console.WriteLine("基類解構函式"); } //解構函式
public static Student operator +(Student student1, Student student2) //運算子過載 +號運算 可以過載多種運算。
{
Student student = new Student(student1.name+student2.name);
return student;
}
public static Student operator +(Student student1, string name2) //運算子過載,為避免過載時的隱式轉化,+必須位於student變數的後面
{
Student student = new Student(student1.name + name2);
return student;
}
public void setname(string name) { Console.WriteLine("基類設定名稱" + name); this.name = name; } //this表示對當前物件的引用
public virtual string getname() { Console.WriteLine("基類獲取名稱" + name); return name; } //使用public方法實現對private資料的控制,保證類內資料安全
public string tast { get; private set; } //自動實現屬性訪問設定器
internal void setage (ref int age){Console.WriteLine("基類設定年齡"+age);this.age=age;} //ref傳遞引用
public virtual void getage(out int age){age=this.age;} //out對未初始化的變數進行保留改變,virtual虛擬函式不能私有
internal static long time = 10; //資料均可在定義時初始化,internal引用當前類的所有類可見
private int age = 0; //private外部不可以訪問
public string name = "student";
static string default_name;
public const int default_age = 12; //const定義常量,定義時賦值,不能是static
public Sextype sextype = new Sextype(); //訪問內部類,編譯器自動生成構造器
public enum allsex { man, woman } //列舉型別,等價於類內組合class allsex{man,woman}
public class Sextype //內部類,無法通過內部類返回外部類的引用,當內部類宣告為static時為巢狀類,巢狀類不屬於物件,而屬於類名
{
public void setsex(allsex sextype)
{
switch (sextype)
{
case allsex.man: sexstring = "man"; break;
case allsex.woman: sexstring = "woman"; break;
default:break;
}
}
private string sexstring;
}
//重寫equals虛擬函式,重寫equals必須重寫gethashcode否則發生警告
public override bool Equals(object another)
{
Console.WriteLine("比較了兩個基類");
if (this.age == ((Student)another).age && this.name == ((Student)another).name)
return true;
return false;
}
//重寫雜湊函式
public override int GetHashCode()
{
return base.GetHashCode(); //呼叫基類的雜湊函式
}
//實現比較函式
public int CompareTo(Student arg0) //要實現排序,必須要實現比較介面
{
return age < arg0.age ? -1 : (age == arg0.age ? 0 : 1); //返回-1表示小於,0表示等於,1表示大於
}
}
//一個檔案可以包含多個類,
abstract class Teacher //abstract宣告抽象類或抽象函式
{
public abstract void setname(); //abstract抽象方法
public string getname() { return name;} //使用public方法實現對private資料的控制
string name = "teacher"; //不加修飾符預設為?
}
sealed class president<T> : Teacher //派生類如果不是抽象,必須重寫全部抽象函式,sealed終態,不能再被繼承
{
public sealed override void setname() { } //sealed函式不能重寫,重寫必須要新增override
private T tt; //設定泛型,也可以使用基本原型object
public T getT() { return tt; } //設定泛型函式,泛型會自動擦除傳遞過來的物件的類資訊
public void setT(T tt) { tt = default(T); this.tt = tt; } //default獲取預設值,引用為null,值型別為0
}
}
Moniter.cs檔案內容如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace csharpdemo
{
public class Moniter:Student,Interface2<String> //可以包含多個介面,實現泛型介面
{
public Moniter():base("monitor"){ //派生類構造器,關鍵字base顯示呼叫基類構造器
Console.WriteLine("派生類無參構造器建立了物件" + name);
}
public Moniter(int age){ //派生類單引數構造器
Console.WriteLine("派生類有參構造器建立了物件"+name);
}
static Student mystudent = new Student("moniter",12); //靜態物件初始化只在使用時刻在進行,在第一個建立類物件或者第一次訪問靜態資料時才初始化
//重寫函式的返回型別可以是基類此方法的返回型別的派生型別
public override string getname() //重寫虛擬函式需要override關鍵字
{
Console.WriteLine("派生類獲取名稱" + name);
//name = base.name + "的派生";
return name;
}
public int getage() { return 11; } //private不能重寫,派生類重名,覆蓋基類私有方法
new string name = "moniter"; //同名變數和靜態變數,不動態繫結到基類引用上,和基類資料儲存在不同的區域,new關鍵字隱藏基類成員
string task = "幫助老師管理班級";
public void init1() //實現介面函式不叫重寫,所以不加override。多介面時應避免介面函式同名
{
Console.WriteLine("實現介面1初始化函式,或介面2初始化函式");
}
public void init2(String name) //泛型介面
{
Console.WriteLine("實現介面2初始化函式");
}
}
}
Interface1.cs檔案內容如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace csharpdemo
{
public interface Interface1 //interface介面,完全抽象類,介面中不能包含欄位
{
void init1(); //abstract抽象方法,介面自動是public的,介面中,不能有函式定義體,abstract可以不寫
}
}
Interface2.cs檔案內容如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace csharpdemo
{
//in抗變泛型,不能使用向上轉型來實現泛型方法,介面也支援繼承,介面可以多繼承,extends後可以有多個子介面,介面可以巢狀在類中<A>泛型介面
interface Interface2<in T>:Interface1
{
void init2(T name); //abstract抽象方法,介面自動是public
new void init1(); //介面隱藏了基介面的函式
}
}
Index.cs主程式檔案內容如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace csharpdemo
{
using System.Text.RegularExpressions; //using為已有型別宣告提供一個新民稱
using myint = System.IntPtr;
class index //自定義類可以新增static,靜態類不能例項化
{
static String stringtemp = "欒鵬除錯";
static void Main(string[] args)
{
var default_age = -2 * -6; //var型別推斷,區域性變數必須顯示初始化,基本型別也通過物件object兌現,只不過只儲存值,是值型別,一元減號用於轉變資料的符號
const string default_name = "student"; //const常量,編譯時用於計算,不能使用變數對其賦值
var students=new {name="students",age=12}; //匿名型別(在例項化時定義)var型別推斷
Student.time+=Student.time<<2+0x21^26; //靜態資料,可以直接通過類名訪問,<<位左移動,低位補零,^按位異或,0x表示16進位制數
Student student1 = new Student(); //所有的物件都必須通過new來建立,基本資料型別可以定義建立
student1.name = student1.getname()+1; //訪問類內資料,字串+過載
student1.setage(ref default_age); //通過類內函式訪問資料
Student.Sextype student1_sextype = new Student.Sextype(); //建立內部類,必須通過外部類變數new構造
student1_sextype.setsex(Student.allsex.man); //呼叫列舉型別
Student student2 = student1; //僅複製引用,兩個變數名指向同一塊記憶體,可通過實現淺拷貝IShallowCopy和深拷貝IDeepCopy實現全面複製
if (student1==student2) //==和!=只是比較物件的引用,不比較物件內容
if(student1.Equals(student2)) //物件的比較使用equals,但是預設的equals還是比較引用,要在自定義類中重寫equals
if(default_age is object) //非布林值不能用在邏輯表示式中,is檢測物件是否與型別相容,int資料也是object繼承來的
printf("建立了兩個相同的類");
Random random=new Random(); //隨機數
int[,] farray = new int[2,3]; //鋸齒陣列[2][3],二維陣列[2,3]
farray[0,0]=random.Next(10,100); //讀取偽隨機序列
Moniter sub1 = new Moniter(); //基類建構函式(繫結後函式),派生類成員,派生類建構函式,介面中的域相當於列舉常量
sprintf(sub1,null); //可變引數,null為空引數
sprintf(sub1); //傳遞實現介面的類,向上轉化為介面,實現函式回撥
Student student3 = new Moniter(); //基類引用,派生類物件
student3.getname(); //呼叫引用動態繫結的方法
((Moniter)student3).getage(); //向下轉型成功
Interface1 interface1 = new Moniter(); //向上轉型,interface1是基類,介面,無所謂,實現介面的類(包含內部類),都可以向上轉化為介面
interface1.init1(); //呼叫動態繫結的函式
List<String> allname=new List<String>(){"小明","曉剛","小紅","曉剛","小劉"};
allname[allname.IndexOf(allname[3])]="小剛"; //[]讀取元素,indexof搜尋,沒有返回-1,
if(!allname.Contains("小王")) //包含元素
allname.Add("小王"); //新增元素
allname.RemoveAt(4); //刪除下標元素
allname.Insert(1,"小韓"); //插入元素
allname.Sort(); //排序
//link查詢,類似於資料查詢語句,查詢操作本地資料集(資料集類似於二維表)查詢語句就是單個元素的判斷
var query = from names in allname where names.StartsWith("小") && names.Length==2 orderby names.Length select names;
foreach(String item in query) //foreach遍歷時,link語句才執行
Console.WriteLine(item);
//list,set,dictionary
Queue<String> allname0=new Queue<String>(); //佇列count元素個數,Enqueue入隊,Dequeue出隊,Peek讀取頭,trimexcess重設容量
Stack<String> allname1= new Stack<String>(); //stack先入後出 堆疊 各種佇列和棧基於linked連結串列實現,count元素個數,push棧頂新增元素,pop棧頂刪除元素,contains是否存在
LinkedList<String> allname2 = new LinkedList<String>(); //雙端佇列,佇列,雙向連結串列
HashSet<String> allname3 = new HashSet<String>(); //包含不重複元素的無序列表
SortedSet<String> allname4 = new SortedSet<String>(); //包含不重複的有序集合
var allstudent1 = new SortedList<int,string>(); //有序列表
//sorteddictionary有序字典,鍵通過gethashcode對映到索引(陣列),索引關連值。多個鍵可以對映到一個索引,一個索引可以關聯多個值
Dictionary<int,string> allstudent2=new Dictionary<int,string>();
try //嘗試執行
{
StringBuilder sb = new StringBuilder(); //stringbuilder包括insert、replace、substring、reverse、append、tostring、delete
sb.Append(String.Format("這裡%s字串相關操作類","shi")); //string.format() 格式化函式,內部建立formatter類設定字串格式
String outstr = sb.ToString().Replace("shi","是"); //string是不可變數,取值變化是生成新的類,replace替換,replaceall,replacefirst
outstr+=outstr.Substring(3)+outstr.Length; //substring取子字串,length字串長度欄位,+過載
if(outstr.IndexOf("shi")<0) //indexof查詢子字串的位置,不存在範圍-1,其他字串相關操作較多
printf("字串不存在子字串");
outstr="luanpeng luanpeng";
outstr = Regex.Split(outstr," ",RegexOptions.IgnoreCase)[0]; //split字串分割,返回陣列,IgnoreCase忽略大小寫
string patter = "l.an"; //建立正則表示式
MatchCollection matcher = Regex.Matches(outstr,patter,RegexOptions.IgnoreCase|RegexOptions.ExplicitCapture); //建立匹配器
foreach(Match nextmatch in matcher) //依次查詢是否存在匹配
printf(nextmatch.Index); //匹配位置
//int aa=0/0;
}
catch (System.Exception ex) //catch函式在try出錯時呼叫,exception為所有異常的基類,異常可以捕獲派生類異常
{
printf("錯誤內容:"+ex.ToString());
Console.WriteLine(ex.StackTrace);
}
finally //finally函式總要執行
{
printf("finally函式總要執行");
}
Student[] all1 = new Student[7]; //
Student[] all2 = new Student[10];
all2=(Student[])all1.Clone(); //複製陣列,陣列元素為引用,則輔助陣列的每一個引用項,引用物件資料不復制
Array.Sort(all2); //呼叫重寫的排序函式執行陣列排序
int location = Array.BinarySearch(all2,student1); //在陣列中查詢,不存在範圍-1
president<Student> sub2 = new president<Student>(); //包含泛型的型別呼叫,也可以不使用泛型建立物件
sub2.setT(student1); //將使用型別替換泛型
//註解
//資料流
//序列化
//Task為後臺執行緒,執行緒池執行緒適合執行短時間程式,均為後臺執行緒,不能設定優先順序
run(); //在主執行緒中呼叫run函式
Parallel.For(2,4,i=>{num=i;run();}); //Parallel.For並行for迴圈,沒有順序,引數i從2到4(不包括4),可以設定提前終止條件
Parallel.ForEach<string>(allname,str=>{stringtemp=str;run();}); //Parallel.ForEach並行遍歷,沒有順序,可以設定提前終止條件
Parallel.Invoke(run,run); //並行執行多個委託
Task t1 = new Task(run); //可以建立時向函式傳遞引數,新任務,使用執行緒池中的執行緒
t1 = new TaskFactory().StartNew(run); //建立任務工廠,並建立啟動新執行緒,使用執行緒池中的執行緒
t1 = Task.Factory.StartNew(run); //靜態屬性factory建立,使用執行緒池中的執行緒
t1=Task.Run(()=>{run();}); //lambda表示式為引數重寫task的run函式,使用執行緒池中的執行緒
//t1.RunSynchronously(); //在當前執行緒(主執行緒),啟動任務
t1=new Task(run,TaskCreationOptions.LongRunning); //新執行緒,不使用執行緒池中的執行緒
t1.Start();
t1.Wait(); //等待執行完成
//ThreadPool.QueueUserWorkItem(run); //選擇執行緒池中的執行緒執行函式,沒有建立執行緒池會先建立再執行
//thread預設是前臺執行緒,適合執行長時間函式
Thread thread =new Thread(run); //呼叫子執行緒,執行run函式
thread=new Thread(()=>Console.WriteLine("lambda執行緒函式")); //呼叫lambda表示式執行緒函式
thread.IsBackground=true; //設定為後臺執行緒
thread.Priority = ThreadPriority.Highest; //設定執行緒優先順序
thread.Start(); //啟動執行緒Start()括號中可以包含一個引數
thread.Join(); //等待執行緒結束
thread.Abort(); //執行緒中斷,會線上程執行至阻塞時中斷
new Thread(run).Start(); //新建執行緒執行函式
//lock(鎖定資源)、Interlocked(提供執行緒安全的遞增遞減交換和讀取值)、Monitor(設定超時,釋放鎖)、waitHandle(等待訊號的出現)
//mutex(多個程序間同步-通過名稱)、semaphore(訊號量可以由多個執行緒使用)、event(事件通知)
bool locktaken=false;
Monitor.TryEnter(stringtemp,500,ref locktaken);
if (locktaken){
printf("同步控制塊執行");
Monitor.Exit(stringtemp); //釋放鎖
}
//在threading、timers、forms、web ui、windows.threading中都有timer,設定重複執行的函式
//System.Timers.Timer mytime= new System.Timers.Timer(1000);
//mytime.AutoReset = true;
//mytime.Elapsed+=run; //回撥函式引數受到限制的(object sender,system.timers.elapsedeventargs e)
//mytime.Start();
//mytime.Stop();
Showdata datashowfun = new Showdata(printf); //以函式為引數例項化委託,作為回撥函式
datashowfun = delegate(string str){Console.WriteLine(str);}; //使用匿名方法實現委託
datashowfun = str=>{Console.WriteLine(str+stringtemp);}; //使用lambda表示式實現委託,lambda表示式可以訪問外部變數,這成為閉包。=>左邊列出引數,右邊複製實現函式
print(datashowfun,"結束"); //委託為引數,呼叫函式
Console.ReadLine();
}
public static void sprintf(Student student, object[] args) //基類引數允許傳遞派生類為引數,object[]用於可變引數列表,可以無參呼叫
{
student.setname("student"); //呼叫動態繫結的基類函式,修改基類成員
printf(student.getname()); //呼叫引用動態繫結的派生類重寫的函式
}
public static void sprintf(Interface1 interface1) //介面引數允許傳遞介面類為引數,sprintf函式名相同實現過載
{
if (interface1 is Moniter) //is判斷,指向物件的具體判斷,不是引用的判斷
{
Student student = interface1 as Student; //先向下轉型為Moniter,在向上轉型為student,as向上轉型,在指定派生類物件的基類引用,可以強制轉化為派生類引用
printf("介面型別:" + interface1.GetType()); //獲取引用指向的物件的型別
student.getname(); //動態呼叫繫結的方法
}
interface1.init1(); //介面相當於純抽象類,動態繫結方法
}
public static void printf<T>(T str) //泛型方法,
{
Console.WriteLine(str.ToString());
}
public delegate void Showdata(string str); //delegate定義委託,委託名為函式型別名,而不是函式變數名。這是一個輸入為字串,返回為空的函式引用,
public static void print(Showdata action, string str)
{
action(str);
}
static int num = 0;
public static void run()
{
num++; //自增自減不是執行緒安全的
Thread.Sleep(1000); //多執行緒,睡眠,不釋放鎖,自動回覆
//await Task.Delay(10); //await一旦完成立即執行,Task.Delay非同步方法,釋放執行緒供其他任務使用,所以此句後面的是新執行緒
printf(num + stringtemp + DateTime.Now);
}
}
}