C#學習之委託 delegate 以及定義、聲明、實例化

學習C#有一段時間了,不過C#的委託+回調才這兩天才會用,以前只是知道怎麼用.前面的一篇文章,函數指針,其實是爲這個做鋪墊的,說白了委託就相當於C語言中的函數指針,具體說用委託有什麼好處,我也不知道,但是因爲你只要學C#那麼回調就一定要會,回調是委託的一種.回調多用於線程間....還是用代碼一點點的說明吧!現在認爲自己以前不會用委託是因爲手太懶,再者沒有太多的必須用C#做的Demo,自己學東西都是用到什麼學什麼,想做什麼東西需要什麼知識就學什麼,前幾天有了必須要做的C#的Demo,關於檢測TCP通信發過來的數據的.扯了這麼多...回調主要的應用是---如果你在一個線程裏操作像文本框,按鈕,Label等組件時,會報錯...原因--C#它不讓這樣操作,,,,

看例子

窗體裏面就放一個textbox

先這樣寫

複製代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace @delegate
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.Text = "123456";
        }
    }
}

複製代碼

結果

 

就這一句   textBox1.Text = "123456";往文本框中寫入123456     程序運行沒問題

 

現在加入線程

複製代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace @delegate
{
    public partial class Form1 : Form
    {
        Thread writeThread;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            writeThread = new Thread(write_Metod);
            writeThread.Start();
        }
        private void write_Metod()
        {
            textBox1.Text = "123456";
        }
    }
}

複製代碼

然後啓動

蹦了

一起動就退出

 說早了.......先說委託

複製代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace @delegate
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            write_Metod();
        }
        private void write_Metod()
        {
            textBox1.Text = "123456";                      
        }
    }
}

複製代碼

這個是沒有用委託的,簡單的例子,程序一運行就執行write_Metod();函數然後文本就打印123456了

現在就用委託來寫一下

 函數名字太長會讓人感覺特複雜有木有....所以下面的名字.....

複製代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace @delegate
{
    public partial class Form1 : Form
    {
        delegate void a();//定義一個委託111111111111111111
        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            a b= new a(c);//實例化2222222222222222222
            b();//3333333333333333333333
        }
        void c()
        {
            textBox1.Text = "123456";                      
        }
    }
}

複製代碼

 

 

 delegate void a();//定義一個委託111111111111111111
這是定義一個委託  要用關鍵字  delegate 
後面的

void a();
函數名字自己取,,不過要有自己的規範,,有自己的一套編程風格就好..
void a();
這是一個沒有返回值的,無參數的函數
因爲學過函數指針都知道,只有類型一樣的函數才能把一個函數的指針(地址)傳給另一個函數..
因爲我們希望把
void c()這個函數用另一個函數代替
這個函數的類型是void 的 無參數的函數

所以就這樣定義了
delegate void a();//定義一個委託----再次說明delegate是關鍵字,意味着定義了一個委託------你說函數指針也行,,C#啊;;;淡化了指針的概念

然後
a b= new a(c);//實例化2222222222222222222

不知道有沒有不知道爲何實例化的
如果不知道實例化那麼知道對象嗎?是C#整的名詞對象
如果不知道對象那麼知道類嗎?,,,,,
上面所說的沒有什麼用的,只是用來嚇唬人的,記得第一次想學高級語言,,,一打開書,,,,,崩潰了,徹底崩潰了,什麼對象,,,,一開頭介紹就是,,,什麼面向對象,,嚇的我趕緊把書方回去,,心有不甘再來一本,,沒想到一打開書...又來了,,,XXXXXX是面向對象的語言,,,,,那時候在想,我去太高深了,,面向對象,,面對誰呢!!  畢向東的JAVA講的不錯....學會一門高級語言,語言有很多共通的地方
又耽誤大家時間了....對了馬士兵的JAVA也挺好,,,都看看  都看看
關於實例化
定義一個A a;假設定義了一個a
如果你不實例化也就是 a = new A();
那麼系統不會爲a開闢任何空間,只有  a = new A();了 系統纔會在內存中爲 a 開闢一段空間,才真正有了a的存在


a b= new a(c);//實例化2222222222222222222
這一句的意思就是
b= c;
哦,原來就是函數指針賦值啊
那麼
b();   就相當於  c();
好再過一遍
先定義一個委託
delegate void a();//定義一個委託

然後實例化---a b = new a(c);
void c()
{

}
這樣   b 就==c了

複製代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace @delegate
{
    public partial class Form1 : Form
    {
        delegate void a();//定義一個委託
        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            a b = new a(c);//實例化
            b();
        }
        void c()
        {
            textBox1.Text = "123456";                      
        }
    }
}

複製代碼

 


 

咱接着

假如說

 void c(string str)
        {
            textBox1.Text = str;                      
        }

那麼我定義的委託(函數指針)也應該是

delegate void a(string str);//定義一個委託

怎樣把c傳過去呢

a b = new a(c);//實例化

然後

b("123456");

因爲c是

void c(string str)
所以
必須寫個string進去嘛

複製代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace @delegate
{
    public partial class Form1 : Form
    {
        delegate void a(string str);//定義一個委託
        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            a b = new a(c);//實例化
            b("123456");
        }
        void c(string str)
        {
            textBox1.Text = str;                      
        }
    }
}

複製代碼



委託也就這樣吧
下面看   回調

窗體不變

複製代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace @delegate
{
    public partial class Form1 : Form
    {
        Thread writeThread;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            writeThread = new Thread(c);
            writeThread.Start();
        }
        private void c()
        {
            textBox1.Text = "123456";
        }
    }
}

複製代碼

然後啓動

程序---崩了

好現在

複製代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace @delegate
{
    public partial class Form1 : Form
    {
        Thread writeThread;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;////////**************************加了這一句
            writeThread = new Thread(c);
            writeThread.Start();
        }
        private void c()
        {
            textBox1.Text = "123456";
        }
    }
}

複製代碼

滿血復活了..

 

System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
上一次程序崩掉是因爲C#不讓跨線程調用窗體控件--不讓在一個新的線程裏調用窗體控件---
textBox1.Text = "123456";就是在使用窗體控件textbox
加上這句System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls
Check  For  Illegal  Cross  Thread  Calls  == false;   不檢查
檢查   對    非法的    交叉    線程    調用
所以就通過了---當自己寫程序時調試可以使用,,真正做項目嘛,,,,,因人而異吧

C#提供了幾種種方法來讓我們在線程裏來操作窗體控件---其它高級語言也提供了相應的方法的
看  回調  來也

複製代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace @delegate
{
    public partial class Form1 : Form
    {
        Thread writeThread;
        delegate void a();//定義回調
        a b;//聲明回調
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            b = new a(d);//實例化回調

            writeThread = new Thread(c);
            writeThread.Start();//啓動C線程
        }
        private void c()
        {
            textBox1.Invoke(b);
        }
        private void d()
        {
            textBox1.Text = "123456";
        }
    }
}

複製代碼

textBox1.Invoke(b);
其實就多了這一句
還可以這樣

複製代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace @delegate
{
    public partial class Form1 : Form
    {
        Thread writeThread;
        delegate void a(string str);
        a b;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            b = new a(d);

            writeThread = new Thread(c);
            writeThread.Start();
        }
        private void c()
        {
            textBox1.Invoke(b,"123456");
        }
        private void d(string str)
        {
            textBox1.Text = str;
        }
    }
}

複製代碼

 

textBox1.Invoke(b,可以帶參數);//這是固定形式,就是這樣用,,,人家規定的
現在放一個按鈕

一啓動

複製代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace @delegate
{
    public partial class Form1 : Form
    {
        Thread writeThread;
        delegate void a(string str);
        a b;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            b = new a(d);

            writeThread = new Thread(c);
            writeThread.Start();
        }
        private void c()
        {
            button1.Invoke(b, "123456");
        }
        private void d(string str)
        {
            button1.Text = str;
        }
    }
}

複製代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章