C#
- foreach
//foreach int[] fibarray = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; foreach (int element in fibarray) { Console.WriteLine(element); } //計數器 int count = 0; foreach(int element in fibarray) { count += 1; Console.WriteLine("Element #{0}:{1}", count, element); } Console.WriteLine("Number of elements in the array:{0}", count);
- 輸出參數out
class NumberManipulator { //按引用傳遞參數 public void swap(ref int x,ref int y) { int temp; temp = x; x = y; y = temp; } //按輸出傳遞參數 /* 就像引用參數,輸出參數的形參擔當實參的别名。方法内對形參的任何改變,在方法執行完成後,通過實參變量都是可見的。 不同的是,輸出參數的要求是: 在方法内部,輸出參數在被讀取之前必須被指派。這意味着,參數的初始值是無關的,而且沒有必要在方法調用之前為實參指派; 在方法傳回之前,方法内部的任何貫穿路徑的可能路徑,都必須為所有輸出參數進行一次指派。 */ public void getValue(out int x) { int temp = 5; x = temp; } static void Main(string[] args) { NumberManipulator n = new NumberManipulator(); int a = 100; int b = 200; Console.WriteLine("交換前,a={0},b={1}", a, b); n.swap(ref a, ref b); Console.WriteLine("交換後,a={0},b={1}", a, b); n.getValue(out a); Console.WriteLine("調用後a的值:{0}", a); } }
- 可空類型(Nullable)
- 單問号?:對int,double,bool等無法付志偉null的資料進行null指派,意思是這個資料類型是Nullable類型
int? i=3; //等價于 Nullable <int> i = new NUllable<int>(3); int i;//預設值0 int? ii;//預設值null
- 雙問号??:Null合并運算符。如果第一個操作數的值為 null,則運算符傳回第二個操作數的值,否則傳回第一個操作數的值。
using System; namespace CalculatorApplication { class NullablesAtShow { static void Main(string[] args) { double? num1 = null; double? num2 = 3.14157; double num3; num3 = num1 ?? 5.34; // num1 如果為空值則傳回 5.34 Console.WriteLine("num3 的值: {0}", num3); num3 = num2 ?? 5.34; Console.WriteLine("num3 的值: {0}", num3); Console.ReadLine(); } } }
- 輸入輸出:System.Console.ReadLine(),System.Console.WriteLine();
- 結構體
- 結構可帶有方法、字段、索引、屬性、運算符方法和事件。
- 結構可定義構造函數,但不能定義析構函數。但是,您不能為結構定義無參構造函數。無參構造函數(預設)是自動定義的,且不能被改變。
- 與類不同,結構不能繼承其他的結構或類。
- 結構不能作為其他結構或類的基礎結構。
- 結構可實作一個或多個接口。
- 結構成員不能指定為 abstract、virtual 或 protected。
- 當您使用 New 操作符建立一個結構對象時,會調用适當的構造函數來建立結構。與類不同,結構可以不使用 New 操作符即可被執行個體化。
- 如果不使用 New 操作符,隻有在所有的字段都被初始化之後,字段才被指派,對象才被使用。
- 類VS結構體
- 類是引用類型,結構是值類型。
- 結構不支援繼承。
- 結構不能聲明預設的構造函數。
- #define預處理器
- Regex類 用于表示一個正規表達式
- 特性
- 特性(Attribute)是用于在運作時傳遞程式中各種元素(比如類、方法、結構、枚舉、元件等)的行為資訊的聲明性标簽。您可以通過使用特性向程式添加聲明性資訊。一個聲明性标簽是通過放置在它所應用的元素前面的方括号([ ])來描述的。
- 特性(Attribute)用于添加中繼資料,如編譯器指令和注釋、描述、方法、類等其他資訊。.Net 架構提供了兩種類型的特性:預定義特性和自定義特性。
- 預定義特性(Attribute)
- AttributeUsage
- Conditional
- Obsolete
-
索引器(Indexer):索引器(Indexer) 允許一個對象可以像數組一樣使用下标的方式來通路。
當您為類定義一個索引器時,該類的行為就會像一個 虛拟數組(virtual array) 一樣。您可以使用數組通路運算符 [ ] 來通路該類的的成員。
//一維索引器 element-type this[int index] { // get 通路器 get { // 傳回 index 指定的值 } // set 通路器 set { // 設定 index 指定的值 } }
- 委托(Delegate):相當于函數指針。
delegate <return type> <delegate-name> <parameter list>
using System; delegate int NumberChanger(int n); namespace DelegateAppl { class TestDelegate { static int num = 10; public static int AddNum(int p) { num += p; return num; } public static int MultNum(int q) { num *= q; return num; } public static int getNum() { return num; } static void Main(string[] args) { // 建立委托執行個體 NumberChanger nc1 = new NumberChanger(AddNum); NumberChanger nc2 = new NumberChanger(MultNum); // 使用委托對象調用方法 nc1(25); Console.WriteLine("Value of Num: {0}", getNum()); nc2(5); Console.WriteLine("Value of Num: {0}", getNum()); Console.ReadKey(); } } } //Value of Num: 35 //Value of Num: 175
-
事件(Event):事件(Event) 基本上說是一個使用者操作,如按鍵、點選、滑鼠移動等等,或者是一些提示資訊,如系統生成的通知。應用程式需要在事件發生時響應事件。例如,中斷。
C# 中使用事件機制實作線程間的通信
- 釋出器(publisher)
- 訂閱器(subscriber)
using System; namespace SimpleEvent { using System; /***********釋出器類***********/ public class EventTest { private int value; public delegate void NumManipulationHandler(); public event NumManipulationHandler ChangeNum; protected virtual void OnNumChanged() { if ( ChangeNum != null ) { ChangeNum(); /* 事件被觸發 */ }else { Console.WriteLine( "event not fire" ); Console.ReadKey(); /* 回車繼續 */ } } public EventTest() { int n = 5; SetValue( n ); } public void SetValue( int n ) { if ( value != n ) { value = n; OnNumChanged(); } } } /***********訂閱器類***********/ public class subscribEvent { public void printf() { Console.WriteLine( "event fire" ); Console.ReadKey(); /* 回車繼續 */ } } /***********觸發***********/ public class MainClass { public static void Main() { EventTest e = new EventTest(); /* 執行個體化對象,第一次沒有觸發事件 */ subscribEvent v = new subscribEvent(); /* 執行個體化對象 */ e.ChangeNum += new EventTest.NumManipulationHandler( v.printf ); /* 注冊 */ e.SetValue( 7 ); e.SetValue( 11 ); } } } /* event not fire event fire event fire */
- 參數數組 params :可變長度參數
class Program { static int SumVals params int[] vals) { int sum=0; foreach (int bal in vals) { sum+=val; } return sum; } static void Main(String[] args) { int sum = SumVals(1,5,2,9,8); Console.WriteLine("Summed Values = {0}",sum); Console.ReadKey(); } }
- ManualResetEvent
通知一個或多個正在等待的線程已經發生的事件,允許線程通過發信号互相通信,來控制線程是否可通路資源。
當一個線程開始一個活動(此活動必須完成後,其他線程才能開始)時,它調用Reset以将 ManualResetEvent 置于非終止狀态。此線程可被視為控制 ManualResetEvent。調用 ManualResetEvent 上的WaitOne的線程将阻止,并等待信号。當控制線程完成活動時,它調用Set以發出等待線程可以繼續進行的信号。并釋放所有等待線程。
一旦它被終止,ManualResetEvent 将保持終止狀态,直到它被手動重置。即對 WaitOne 的調用将立即傳回。
開啟後預設不關閉,需要手動關閉。
using System;
using System.Threading;
namespace ManualResetEventTest
{
class Program
{
static ManualResetEvent mre = new ManualResetEvent(true);
static ManualResetEvent mre = new ManualResetEvent(false);
static void Main(string[] args)
{
//Console.WriteLine("Start!");
Thread[] threads = new Thread[3];
//Console.WriteLine("New Thread Finished!");
for (int i = 0; i < 3; i++)
{
threads[i] = new Thread(ThreadRun);
threads[i].Start();
}
Console.WriteLine("Hello,World!");
}
static void ThreadRun()
{
int _threadID = 0;
while (true)
{
mre.WaitOne();
_threadID = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("current Tread is " + _threadID);
Thread.Sleep(TimeSpan.FromSeconds(2));
}
}
}
}
_mre初始化為false時,為非終止狀态
_mre初始化為True時,為終止狀态
終止狀态時 WaitOne()允許線程通路下面的語句,非終止狀态時不可以。
在非終止狀态時想讓線程繼續執行和停下來,需要使用Set()和Reset()方法。
using System;
using System.Threading;
namespace ManualResetEventTest
{
class Program
{
static ManualResetEvent _mre = new ManualResetEvent(false);
static void Main(string[] args)
{
Console.WriteLine("輸入1為Set() 開始運作");
Console.WriteLine("輸入2為Reset() 暫停運作");
Thread[] _threads = new Thread[3];
for (int i = 0; i < 3; i++)
{
_threads[i] = new Thread(ThreadRun);
_threads[i].Start();
}
Console.WriteLine("Finish create threads!");
while (true)
{
Console.WriteLine("Ready to read!");
char c = Console.ReadLine()[0];
Console.WriteLine("Finish read!");
switch (c)
{
case '1':
Console.WriteLine("Ready to run!");
_mre.Set();
Console.WriteLine("開始運作");
break;
case '2':
Console.WriteLine("Ready to stop!");
_mre.Reset();
Console.WriteLine("暫停運作");
break;
default:
Console.WriteLine("default!");
break;
}
}
}
static void ThreadRun()
{
int _threadID = 0;
while (true)
{
_threadID = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("current Tread is " + _threadID);
Thread.Sleep(TimeSpan.FromSeconds(2));
_mre.WaitOne();
}
}
}
}
- WaitOne()
-
WaitOne(),Wait(int),Wait(timespan,bool)
int裡面是毫秒,如果在規定時間内set則阻塞後繼續運作,傳回值為true;如果沒有在規定時間内傳回,則傳回值為false下次運作時不會再走這一步。
using System; using System.Threading; namespace testmono { class WaitOne { static ManualResetEvent autoEvent = new ManualResetEvent(false); static void Main() { Console.WriteLine("Main starting."); ThreadPool.QueueUserWorkItem(new WaitCallback(WorkMethod), autoEvent); // Wait for work method to signal. while(!autoEvent.WaitOne(100)) { //Console.WriteLine("Work method signaled."); Console.WriteLine("Timed out waiting for work " + "method to signal."); } Console.WriteLine("Main ending."); } static void WorkMethod(object stateInfo) { Console.WriteLine("Work starting."); // Simulate time spent working. Thread.Sleep(new Random().Next(100, 2000)); // Signal that work is finished. Console.WriteLine("Work ending."); ((ManualResetEvent)stateInfo).Set(); } } }
- get set
C#的特殊用法,其實是控制通路權限,get可讀,set可寫。
- ThreadStrat 和 ParameterizedThreadStart
差別:委托定義的函數是否能接受參數,ThreadStart不可以,ParameterizedThreadStart可以接受一個參數。
但因為可以把多個參數封裝到一個類中,是以相當于ParameterizedThreadStart可以接受多個參數。
using System;
using System.Threading;
class AddParams
{
public int a, b;
public AddParams(int numb1, int numb2)
{
a = numb1;
b = numb2;
Console.WriteLine("AddParams!");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Adding with Thread objects *****");
Console.WriteLine("ID of thread in Main(){0}" ,Thread.CurrentThread.ManagedThreadId);
AddParams ap = new AddParams(10, 10);
//委托
Thread t = new Thread(new ParameterizedThreadStart(Add));
Thread.Sleep(200);
Console.WriteLine("t has been created");
t.Start(ap);
Console.ReadLine();
}
#region Add method
static void Add(object data)
{
if (data is AddParams)
{
Console.WriteLine("ID of thread in Main(): {0}" ,Thread.CurrentThread.ManagedThreadId);
AddParams ap = (AddParams)data;
Console.WriteLine("{0} + {1} is {2}",ap.a, ap.b, ap.a + ap.b);
}
}
#endregion
}