2013年4月11日 星期四

可多項判斷的switch case: break; default:

利用下拉式選擇幾月份
switch帶入條件
case做季節判斷 並SHOW出訊息
直到break跳出程式區塊
default則是例外處理
來看下面範例

private void btn_true_Click(object sender, EventArgs e)
        {
            switch (cbox_select.SelectedIndex + 1)//Selectedindex由0開始所以+1
            {
                case 3://如果是3.4.5月
                case 4:
                case 5:
                    MessageBox.Show("春季", "提示!");
                    break;//跳出程式區塊
                case 6://如果是6.7.8月
                case 7:
                case 8:
                    MessageBox.Show("夏季", "提示!");
                    break;
                case 9:
                case 10:
                case 11:
                    MessageBox.Show("秋季", "提示!");
                    break;
                case 12:
                case 1:
                case 2:
                    MessageBox.Show("冬季", "提示!");
                    break;
                default://如果沒有選擇月份彈出提示訊息
                    MessageBox.Show("請選擇月份", "提示!");
                    break;
            }
        }


不只可以做數值判斷 也可以做 字串與布林的判斷

下面範例為 判斷 True與Flase


private void button1_Click(object sender, EventArgs e)
        {
            switch (radioButton1.Checked)
            {
                case true:
                    MessageBox.Show("true");
                    break;
                case false:
                    MessageBox.Show("false");
                    break;
            }
        }




再來是字串上的判斷範例如下


 private void button2_Click(object sender, EventArgs e)
        {
            switch (comboBox1.SelectedItem.ToString())
            {
                case "左楠":
                    MessageBox.Show("加油站");
                    break;
                case "NXP":
                    MessageBox.Show("半導體");
                    break;
                case "請選擇公司名稱":
                    MessageBox.Show("請點選下拉式清點選擇");
                    break;
            }
        }




上面程式碼在執行過程中 出了一點問題

來記錄一下在製作範例過程遇到的問題與排除方式
原因如下:
發現如果使用者,選空白選項時
不能使用default來使用例外處裡,原因是
在selectedindex為null值時,無法做ToString轉換
下面稍微研究 整理出幾套方法

本來想在combobox.Text直接輸入"請選擇"
結果不行? 因為
設定combobox的DropDownStyle是DropDownList
時不能對Text修改 改了按下ENTER之後一樣空白
後來才知道 要在ITEM加入"請選擇"
直接指定TEXT才可以
下面紀錄設定DropDownList又可以避免null的方法



第一招,直接在Item中新增一個"請選擇"
並且在 程式開啟時
設定combobox的text值為combobox.Item[0].ToString()
讓combobox保持在第一項新增的"請選擇"項目

下面範例同上,下面只是加入設定,combobox.text

private void Frm_Main_Load(object sender, EventArgs e)
{//item[0]以字串指定給text程式開啟瞬間已經設定好
  comboBox1.Text = comboBox1.Items[0].ToString();
}



@@再來查略一下控制項屬性
發現到一個更簡單的方法
可讓defalut發揮作用
紀錄如下

private void button2_Click(object sender, EventArgs e)
        {
            switch (comboBox1.Text)//直接判斷text就好
            {
                case "左楠":
                    MessageBox.Show("加油站");
                    break;
                case "NXP":
                    MessageBox.Show("半導體");
                    break;
                default:
                    MessageBox.Show("請選擇");
                    break;
            }
        }

2013年4月9日 星期二

combobox識別身分範例與item導入物件概念

下面簡單介紹combox中的基礎應用
在item屬性中分別 加入admin與user
在使用IF ELSE進行判斷用戶
下面範例

        private void btn_login_Click(object sender, EventArgs e)
        {
            //下面判斷如果選擇是一個叫"admin"的話true
            if (cbox_select.SelectedItem.ToString() == "admin")
            {
                MessageBox.Show(//如果是admin登陸則提示管理員登陸
                    "管理員登入", "提示!");
            }
            else//如果不是false
            {
                MessageBox.Show(//如果是user登陸則提示普通用戶登陸
                    "普通用戶登入", "提示!");
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            cbox_select.SelectedIndex = 0;//默認選擇combobox中的第一項
        }

防止用戶誤觸修改combobox中的內容,可設定DropDownStyle屬性中的DropDownList即可


由於顯示一般是字串物件,但item.add方法 可接受物件
而下拉式清單會呼叫item中每一個objecy中的字串方法
並顯示在combobox中
所以可以利用此特性 建立類別 再利用add加入新物件
下面修改後的範例

public partial class Frm_Main : Form
    {
        class ttest
        {
            //因為Items集合中的add方法接受"物件"
            //
            //用override重新定義ToString()
            //item會呼叫物件中的ToString()方法
            //而ToStrung()是一個方法
            //但是一旦執行ttest 遇到override ToString()就必須重新定義
            //利用OVERRIDE複寫基底的TOSTRING
            //當呼叫ttest類別時 呼叫字串 override會複寫ToString
            //而tostring 回傳一個字串"程式設計"給 Add
            public override string ToString()
            {
                return "程式設計";//建立字串方法 傳回"程式設計"
            }
        }
        public Frm_Main()
        {
            InitializeComponent();
        }
        private void btn_login_Click(object sender, EventArgs e)
        {
            //下面判斷如果選擇是一個叫"admin"的話true
            if (cbox_select.SelectedItem.ToString() == "admin")
            {
                MessageBox.Show(//如果是admin登陸則提示管理員登陸
                    "管理員登入", "提示!");
            }
            else//如果不是false
            {
                MessageBox.Show(//如果是user登陸則提示普通用戶登陸
                    "普通用戶登入", "提示!");
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            //ttest objectName = new ttest();
            //or
            //直接new
            cbox_select.Items.Add(new ttest());//加入新物件 
            cbox_select.SelectedIndex = 0;//默認選擇combobox中的第一項
        }

簡潔的使用if eles或?:做邏輯判斷

雖然是常使用的if else判斷式 不過複習到這裡就在寫一篇 當作幫助記憶

簡單的利用if else 就好略讀 也可以做 窩狀複合式判斷 較複雜不提!
基本概念範例就可如法炮製 看下面

private void btn_go_Click(object sender, EventArgs e)
        {
            if (rbtn_school.Checked)//判斷小明去學校還是去醫院
            {
                MessageBox.Show("向左走", "提示!");//如果去學校則向左走
            }
            else
            {
                MessageBox.Show("向右走", "提示!");//如果去醫院則向右走
            }
        }



可使用三元運算使得程式更簡潔
請看下面

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show(rbtn_school.Checked ? "走左邊" : "走右邊","我是標題");
        }




三元運算 一行搞定@@不過很少使用 不太熟悉 要來研究一下
if else較彈性也可搭配複合邏輯判斷與渦狀 比較熟悉

2013年4月8日 星期一

使用as來轉換

下面簡單列子 示範利用簡單的as將object轉換指定型態


private void button1_Click(object sender, EventArgs e)
        {
            string Q = "TEST";//建立一個字串
            object W = Q;//字串轉物件
            string A = W as string;//物件轉回字串 判斷是否成功
            if (A != null)//A不等於null
            {
                MessageBox.Show("OK");//成功 show出ok
            }
            else//A等於null
                MessageBox.Show("不OK");
        }




再來,來看個轉型不成功null的例子
private void button1_Click(object sender, EventArgs e)
        {
            int Q=1;
            object W = Q;
            string A = W as string;
            if (A != null)
            {
                MessageBox.Show("OK");
            }
            else
                MessageBox.Show("不OK");//在判斷時無法成功轉型因此A還是NULL
        }

嘗試轉成型別int 或 double 數值型態valueType
結果發現 編譯器SHOW出(int is a non-nullable value type)
才驚覺發現 原來有使用上的限制
原因是轉換過程是if做null判斷
所以不可以使用valueType數值類型 比如說 int double 之類的
不然連執行都不能執行 編譯將會出現錯誤

下面示範 連執行都不能執行的 列子

private void button1_Click(object sender, EventArgs e)
        {
            int Q=1;
            object W = Q;
            int A = W as int;
            if (A != null)
            {
                MessageBox.Show("OK");
            }
            else
                MessageBox.Show("不OK");
        }

2013年4月6日 星期六

使用is關鍵字判斷物件是否與指定類型一樣

程式開發過程,因型態時常的轉換 或 轉換不成功 ,出現異常增加不穩定性
使用 is 關鍵字 可以判斷 是否與指定類型相同?  相容true 不相容false

下面簡單的概念

private void button1_Click(object sender, EventArgs e)
        {
            string PP = "程式設計";//建立字串型態
            object OBJ = PP;//將字串轉物件
            if (OBJ is string)//查詢OBJ是不是STRING
            {
                MessageBox.Show("OBJ 是一個strin型態");
            }
            else
            {
                MessageBox.Show("不是string型態");
            }
        }


在看以下範例


  private void btn_Get_Click(object sender, EventArgs e)
        {
            //下面是radiobutton 裡用?:三元運算做判斷 true 是字串 false 是檔案型態
            //面板上有 radiobutton1 與2
            object P_obj = rbtn_target1.Checked ?
                (object)"C# 編程詞典" : new System.IO.FileInfo(@"d:\");
            if (rbtn_class1.Checked)//判斷選擇了哪一個類型
            {
                if (P_obj is System.String)//判斷物件是否為字符串類型
                    MessageBox.Show(//提示相容訊息
                        "物件與指定類型相容", "提示!");
                else
                    MessageBox.Show(//提示不相容訊息
                        "物件與指定類型不相容", "提示!");
            }
            else
            {
                if (P_obj is System.IO.FileInfo)//判斷物件是否為文件類型
                    MessageBox.Show(//提示相容訊息
                        "物件與指定類型相容", "提示!");
                else
                    MessageBox.Show(//提示不相容訊息
                        "物件與指定類型不相容", "提示!");
            }
        }

2013年4月3日 星期三

資源回收方法與基礎

前篇 理解記憶體配置之後 可以開始記錄如何有效管理記憶體的配置

建立類別 與 解構

先建立類別 利用~來解構類別 並SHOW出訊息告知已解構
class Father
        {
            public Father()
            {
                MessageBox.Show("類別狀態:建構 Father");
            }
            ~Father()
            {
                MessageBox.Show("類別狀態:解構 Father");
            }
        }
       
        class Son : Father
        {
            public Son()
            {
                MessageBox.Show("類別狀態:建構 Son");
            }
            ~Son()
            {
                MessageBox.Show("類別狀態:解構 Son");
            }
        }




再來 來試試看 執行的步驟 建立BUTTON
private void button1_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = "程式開始" + "\n"; ;
            Son me = new Son();
            me = null;
            richTextBox1.Text += "程式結束" + "\n";
            //直到程式被關閉 才會執行解構
        }



執行 先後順序 如下
程式開始
建構FATER
建構SON
程式結束
會發現程式 尚未解構 
直到把程式關閉 才SHOW出 解構訊息
因為使用~來解構 會呼叫Object.Finalize方法
而Finalize只是 允許物件在記憶體回收進行回收之前,嘗試釋放資源並執行其他清除作業。

下面列子中 與上一樣 不同與加入 GC強迫回收!
PS:使用 同上一樣的類別
private void button2_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = "程式開始" + "\n";
            Son me = new Son();
            me = null;
            richTextBox1.Text += "開始執行強迫回收"+"\n";
            //以GC指令強迫.Net framework資源回收
            GC.Collect();
            //並使用WaitForPendingFinalizers method等到確實回收後
            //再繼續執行,因為資源回收時是在另一個thread之故。
            GC.WaitForPendingFinalizers();
            richTextBox1.Text += "程式結束" + "\n";
        }

執行順序為
程式開始
建構FATER
建構SON
解構SON
解構FATER
程式結束

可以程式尚未結束 先進行回收




再來可以使用IDisposable介面
類別程式碼如下
class FFather : IDisposable //父類別直接指向IDisposable
        {
            public FFather()
            {
                MessageBox.Show("類別狀態:建構 FFather");
            }
            public void Dispose()
            {
                MessageBox.Show("類別狀態:解構 FFather");
            }
        }
        class SSon : FFather, IDisposable
        {
            public SSon()
            {
                MessageBox.Show("類別狀態建構 SSon");
            }
            new public void Dispose()
            {
                MessageBox.Show("類別狀態解構 SSon");
            }
        }




一樣寫個BUTTON來看執行順序

private void button3_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = ("程式開始");
            using (SSon me = new SSon())
            {
                richTextBox1.Text += ("程式執行中");
            }
            richTextBox1.Text += ("程式結束");
            //只有呼叫子類別的回收
        }



執行順序如下
程式開始
建構FFATHER
建構SSON
解構SSON
程式結束

PS:一定會覺得奇怪 FFATHER怎沒被解構?

Net framework只呼叫子類別的Dispose method 卻沒有呼叫父類別的Dispose method,所以,實作IDisposable介面時,父類別的資源回收要由子類別呼叫

請看下面 類別改寫 加入base.Dispose()


class FFFather : IDisposable //父類別直接指向IDisposable
        {
            public FFFather()
            {
                MessageBox.Show("類別狀態:建構 FFFather");
            }
            public void Dispose()
            {
                MessageBox.Show("類別狀態:解構 FFFather");
            }
        }
        class SSSon : FFFather, IDisposable
        {
            public SSSon()
            {
                MessageBox.Show("類別狀態建構 SSSon");
            }
            new public void Dispose()
            {
                MessageBox.Show("類別狀態解構 SSSon");
                base.Dispose();
            }
        }


執行順序如下
程式開始
建構FFFATHER
建構SSSON
解構SSSON
解構FFFATHER
程式結束


注意使用  IDisposable介面時候
建立物件時 務必使用 using
如果不使用using IDisposable將毫無作用


資源釋放觀念整理 與 回收方法實作與Box Unbox

 
 
寫C#程式也有一段時間了,算一算現在寫的這個程式已是第四個用C#寫的較有規模的程式。一直以來因為懶惰和玩不完的電動,都沒有好好去研究C#中資源釋放的問題,尤其後來這三次寫的程式都需要用到以C++寫成的Library(以C++/CLI寫一個Wrapper Class來包裝),有二次要用到Managed DirectX,對於各種資源的管理更顯得重要。所以這一次就稍微認真了點,去搜尋了一下C#資源釋放的相關文章來做個統整。

剛接觸C#沒多久的人,通常對於GC(Garbage Collector)都會跟我有一樣的茫然,「GC什麼時候會回收資源?」、「哪些東西會被GC回收?」、「太倚賴GC是不是會造成程式效率低落?」,以下就從基礎開始談起GC的運作機制。