天天看點

C#基礎文法-以Cpp為參照C#

C#

  1. 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);
               
  2. 輸出參數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);
            }
        }
               
  3. 可空類型(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();
    
          }
       }
    }
               
  4. 輸入輸出:System.Console.ReadLine(),System.Console.WriteLine();
  5. 結構體
    • 結構可帶有方法、字段、索引、屬性、運算符方法和事件。
    • 結構可定義構造函數,但不能定義析構函數。但是,您不能為結構定義無參構造函數。無參構造函數(預設)是自動定義的,且不能被改變。
    • 與類不同,結構不能繼承其他的結構或類。
    • 結構不能作為其他結構或類的基礎結構。
    • 結構可實作一個或多個接口。
    • 結構成員不能指定為 abstract、virtual 或 protected。
    • 當您使用 New 操作符建立一個結構對象時,會調用适當的構造函數來建立結構。與類不同,結構可以不使用 New 操作符即可被執行個體化。
    • 如果不使用 New 操作符,隻有在所有的字段都被初始化之後,字段才被指派,對象才被使用。
  6. 類VS結構體
    • 類是引用類型,結構是值類型。
    • 結構不支援繼承。
    • 結構不能聲明預設的構造函數。
  7. #define預處理器
  8. Regex類 用于表示一個正規表達式
  9. 特性
    • 特性(Attribute)是用于在運作時傳遞程式中各種元素(比如類、方法、結構、枚舉、元件等)的行為資訊的聲明性标簽。您可以通過使用特性向程式添加聲明性資訊。一個聲明性标簽是通過放置在它所應用的元素前面的方括号([ ])來描述的。
    • 特性(Attribute)用于添加中繼資料,如編譯器指令和注釋、描述、方法、類等其他資訊。.Net 架構提供了兩種類型的特性:預定義特性和自定義特性。
  10. 預定義特性(Attribute)
    • AttributeUsage
    • Conditional
    • Obsolete
  11. 索引器(Indexer):索引器(Indexer) 允許一個對象可以像數組一樣使用下标的方式來通路。

    當您為類定義一個索引器時,該類的行為就會像一個 虛拟數組(virtual array) 一樣。您可以使用數組通路運算符 [ ] 來通路該類的的成員。

    //一維索引器
    element-type this[int index]
    {
       // get 通路器
       get
       {
          // 傳回 index 指定的值
       }
    
       // set 通路器
       set
       {
          // 設定 index 指定的值
       }
    }
               
  12. 委托(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
               
  13. 事件(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
    */
               
  14. 參數數組 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();
    	}
    }
               
  15. 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();
            }
        }
    }
} 
           
  1. 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();
    
            }
    
        }
    }
               
  1. get set

C#的特殊用法,其實是控制通路權限,get可讀,set可寫。

  1. 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
}