-----------------委托的使用场合 (使用方式)----------------

《委托的使用示例》

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 委托的本质
{
    public delegate void MyDelegate(); //定义一个委托
    public class Test
    {
        //委托说白了就是一个数据类型,就像string 类型接收字符串数据 int类型接收整形数据, 而委托类型接收方法

        public string Name { get; set; }  //定义一个属性

        public MyDelegate mydele; //定义一个委托变量

        public int i;    //定义一个整形变量

        public Test abc; //定义一个Test类型的变量。



        public void MyTest(string str,MyDelegate myde)
        { 
            //我在Main 函数中调用 这个MyTest方法,注意,我们传递了两个参

            //此时: str的值为:"张三" 这个字符串

            //此时: myde的值为:Program.Pro 这个方法 (所以,这里是把Program.Pro这个方法当做一个参数在传递)

            this.Name = str; //此时Name的值就是“张三”这个字符串

            this.mydele = myde;  //此时的mydele的值就是Program.Pro方法了。(如果给this.mydele赋了值,在当前方法以外,我们就可以使用mydele这个委托了,比如在Haha()方法中,当然在当前方法中也可以直接用,比如直接执行myde委托,货这执行赋了值之后的this.mydele委托)   
        }

        public void Haha()
        {
            this.mydele();
        }   
    }

    class Program
    {
        public static void Pro()
        {
            Console.WriteLine("嗨!我是一个方法!");
        }
        static void Main(string[] args)
        {

            Test t = new Test();
            t.MyTest("张三", Program.Pro);
            t.Haha();

            Console.Read();

        }
    }
}


//类是一种数据类型,它是用来存储类的对象的
public class MyClass  //类的定义方式
 MyClass c=new MyClass(); //类的使用方式

//委托也是一种数据类型,委托这个数据类型用来存储方法的。
public deletage void MyDelegate() //委托的定义方式

//既然委托是用来存储方法的,声明一个委托类型,new一个就可以存储一个方法
MyDelegate myde=new MyDelegate(这里是一个无参,无返回值的方法)  //委托的使用方式

<pre class="csharp" name="code">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 委托
{
    //委托可以定义在类里面,但是一般我们不那样做,除非特殊情况。因为委托是和类平级的,所以委托一般定义在namespace下面

    //定义一个委托,用来保存无返回值,无参数的方法
    public delegate void MyDelegate(); 
    class Program
    {
        public void M1()
        {
            Console.WriteLine("哈哈!");
        }
        static void Main(string[] args)
        {
            Program p = new Program();

            MyDelegate md = new MyDelegate( p.M1); 
			
	   //上面这一步我们可以简写 直接写成 MyDelegate md=p.M1 就行;但是委托对象一定是要赋值给一个委托对象的,在这里看起来是直接把p.M1 这个方法赋值给md对象了。其实是编译器内部会给我们new了一个委托对象的,也就是说编译器自动给我们完成了MyDelegate md = new MyDelegate( p.M1); 
			
			

            Console.WriteLine("..............................");
            Console.WriteLine("..............................");

            md(); //这里使用委托简直的多此一举,我们直接调用M1方法就可以了。没有必要在这里使用委托。但是这里我们仅仅是演示一下委托的使用而已

            Console.WriteLine("..............................");
            Console.WriteLine("..............................");
            Console.WriteLine("OK");
            Console.ReadKey();

        }
    }
}

 

《委托的使用场合1----挖坑,填坑》

新建一个解决方案。

1,在里面创建一个类库。默认命名为:ClassLibrary1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClassLibrary1
{
    public class TestClass1
    {
        public void DoSomething()
        {
            Console.WriteLine("..........................");//这里可能是连接数据库的操作代码
            Console.WriteLine("..........................");//这里可能是对文件操作的代

            Console.WriteLine(DateTime.Now.ToString()); //在这里输出当前时间

            Console.WriteLine("..........................");
            Console.WriteLine("..........................");
            Console.WriteLine("OK");
            Console.ReadKey();
     
        }
    }
}

下面我们创建一个控制台应用程序 命名为:TestDelegateApp1,并给它添加引用ClassLibrary1这个类库

using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestDelegateApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            TestClass1 tc = new TestClass1();
            tc.DoSomething();
        }
    }
}

执行TestDelegateApp1这个控制台项目,产生了如下输出:



接着,我们在解决方案下面,再添加一个控制台应用程序,命名为:TestDelegateApp2

在TestDelegateApp2这个控制台应用程序里我的需求变了:还是输出上面那一幅图里面的虚线,但是中间那一行日期不在进行输出了,而是将中间那一行日起写入到一个文件中,如果这样的话,我们就需要修改ClassLibrary1这个类库的TestClass1.cs文件。将它修改为

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClassLibrary1
{
    public class TestClass1
    {
        public void DoSomething()
        {
            Console.WriteLine("..........................");//这里可能是连接数据库的操作代码
            Console.WriteLine("..........................");//这里可能是对文件操作的代

            File.AppendAllText(@"d:\nono.txt",DateTime.Now.ToString());

            Console.WriteLine("..........................");
            Console.WriteLine("..........................");
            Console.WriteLine("OK");
            Console.ReadKey();
     
        }
    }
}


然后再TestDelegateApp2这个控制台中也引用一下ClassLibrary1这个类库,

using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestDelegateApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            TestClass1 tc = new TestClass1();
            tc.DoSomething();
        }
    }
}

运行TestDelegateApp2这个控制台应用程序,产生如下输出:

在去D盘下的nono.txt文件看看,当前时间也已经写入了

-----------------------------------------------------------------------------------------------------------

那么问题来了。每次我变化一下需求,就要改一下ClassLibrary1类库中的代码,而且我的项目中,有好几处都需要调用ClassLibrary1这个类库中的TestClass1.cs这个类中的DoSomething方法,而大家仅仅是对日期那一部分有不同的需要而已,如果大家都改ClassLibrary1类库中的TestClass1类中的DoSomething()方法是不合适的。

于是我们想到一个办法。那就是使用委托,将日期那一部分用一个委托代替(我们知道委托是存储方法的),谁有不同的需求,就实现这个委托不就得了?

那下面我就将ClassLibrary1类库中TestClass类中的DoSomething()方法改成如下这样:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClassLibrary1
{
    public delegate void Mydelegate();
    
    public class TestClass1
    {       
        public void DoSomething(Mydelegate myde)
        {
            Console.WriteLine("..........................");//这里可能是连接数据库的操作代码
            Console.WriteLine("..........................");//这里可能是对文件操作的代

            myde(); //在这里放一个委托。谁想在这里实现什么功能,只要去实现这个委托就好了(委托就像母版页一样,在这里挖一个坑,想实现什么功能,就来填坑)

            Console.WriteLine("..........................");
            Console.WriteLine("..........................");
            Console.WriteLine("OK");
            Console.ReadKey();
     
        }
    }
}

然后我们再看看TestDelegateApp1控制台应用程序的代码

using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestDelegateApp1
{
    class Program
    {
        public static void abc()
        {
            Console.WriteLine(DateTime.Now.ToString());
        }
        static void Main(string[] args)
        {
            TestClass1 tc = new TestClass1();
            tc.DoSomething(abc);
        }
    }
}

再来看看TestDelegateApp2这个控制台应用程序的代码:

using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestDelegateApp2
{
    class Program
    {
        public static void abc()
        {
            File.AppendAllText(@"d:\nono.txt", DateTime.Now.ToString());
        }
        static void Main(string[] args)
        {
            TestClass1 tc = new TestClass1();
            tc.DoSomething(abc);
        }
    }
}




《委托的使用场合2----挖坑,填坑》

新建一个解决方案。

1,在里面创建一个类库。默认命名为:ClassLibrary1

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClassLibrary1
{
    public delegate string Mydelegate(string str);
    
    public class TestClass1
    {       
        public void ChangeStrings(string[] str,Mydelegate myde)
        {
            for (int i = 0; i < str.Length; i++)
            {
                //需求:我要对str这个数组的项进行处理

                //1,将str这个数组的每一项前后都加一个*  在TestDelegateApp1这个控制台应用程序里实现这个功能

                //2, 将str这个数组的小写字母,全转换成大小字母, 在TestDelegateApp2这个控制台应用程序里实现这个功能

                Console.WriteLine(str[i] = myde(str[i]));//我在这里有使用委托你看的出来吗? 将委托的放回值赋值给str的每一项,就实现这个目的了
                
            }
            Console.ReadKey();
     
        }
    }
}
下面我们创建一个控制台应用程序 命名为:TestDelegateApp1,并给它添加引用ClassLibrary1这个类库
using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestDelegateApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            string[] str = new string[] { " 张三", " 李四", " 王五", " 赵六" };

            TestClass1 tc = new TestClass1();
            for (int i = 0; i < str.Length; i++)
            {
                tc.ChangeStrings(str, abc);
            }

        }

        public static string abc(string s)
        {
            return "*" + s + "*";
        }
     
    }
}

执行TestDelegateApp1这个控制台项目,产生了如下输出:


接着,我们在解决方案下面,再添加一个控制台应用程序,命名为:TestDelegateApp2

using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestDelegateApp2
{
    class Program
    {
        public static void abc()
        {
           
        }
        static void Main(string[] args)
        {
            string[] str = new string[] { "zhangshang", "lisi", "wangwu", "zhaoliu" };

            TestClass1 tc = new TestClass1();
            for (int i = 0; i < str.Length; i++)
            {
                tc.ChangeStrings(str, abc);
            }

             Console.ReadKey();
        }

        public static string abc(string name)
        {
            return name.ToUpper();
        }
    }
}
运行TestDelegateApp2这个控制台应用程序产生了如下输出:



项目图


《委托单使用场合3----窗体之间传值》

首先在解决方案下创建一个窗体应用程序。需求如下图:

Form1类中 即From1窗体中的代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 委托案例_窗体之间通过委托传值
{
    public delegate void UpdateFrom1TextBox(string s);
    public partial class Form1 : Form
    {
       
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 f2 = new Form2(textBox1.Text, UpdateTextBox);//创建Fom2类对象,将UpdateTextBox方法作为参数来传递到From2类中,用于初始化From2类中的委托变量。(注意;委托变量接收的是方法,所以要初始化Form2中的委托变量,就要让它接收一个方法,所以这里我们传递一个方法过去)
            f2.Show();
            
        }

        //写这个方法的目的是在Form2窗体中跟新Form1窗体(当前窗体)中的TextBox1的值 (因为我在Form2窗体的构造函数中重载了一个带2个参数的Form2窗体的构造函数;第一个参数是一个string类的值,第二个参数是一个委托,,我们在From1类中创建一个Form2类的对象,然后传递2个参数,它就会自动的调用带2个参数的构造函数了。既然是第二个参数是一个委托,这样就可以将这个方法当做参数传递过去,然后再From2中定义一个委托变量,在这个带两个参数的构造函数执行的时候,我再给Form2类中的的那个委托变量赋值为传过去的方法(即当前这个方法),然后再Fom2类中去执行这个委托,而执行这个委托就是执行UpdateTextBox这个方法。所以就实现了在Form2类中更新Form1类的中的TextBox值了)
        private void UpdateTextBox(string value)
        {
            textBox1.Text = value;
        }
        
    }
}

Form2窗体中的代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 委托案例_窗体之间通过委托传值
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();//这句话是初始化对象窗口
        }
        //因为委托是与类同一级别的,它一般是定义在namespace下面,所以Form1类与Form2类都可以访问它(注意:窗体1是Form1类,和窗体2是Form2类 都是在同一名称空间下)
        public Form2(string str,UpdateFrom1TextBox update)
        {
            InitializeComponent();
            this.textBox1.Text = str;
            this._update = update; //因为在Form1类中button1_Click事件中创建了一个Form2的类对象,是调用的Form2类带2个参数的构造函数,即当前的这个构造函数:Form2 f2 = new Form2(textBox1.Text, UpdateTextBox); 因为当前构造函数的第二个参数是一个委托类型,而委托类型是存储方法的,而正好这里又在Form1类中创建的这个Form2类对象的时候 传递了一个UpdateTextBox方法过来。  这里的this._update = update 就表示给当前类下的这个_update委托变量初始化赋值。赋的什么值呢?答:赋的是从Form1类中传过来的UpdateTextBox方法。
           
        }
        private UpdateFrom1TextBox _update; //定义一个委托变量。
        private void button1_Click(object sender, EventArgs e)
        {
            this._update(textBox1.Text); //这里执行_update这个委托,其实就是执行UpdateTextBox这个方法。所以在执行this.Close()关闭当前窗口之前,会执行UpdateTextBox这个方法 (这个方法就是更新Form1类中的TextBox1的值)
            this.Close();
        }
    }
}

要注意的一个地方就是。当在From1窗体中,我们可以new一个Form2传递对象,通过重载From2窗体的构造函数将Form1类中的一些数据传递给Form2窗体中的,
而在Form2传递中却不能通过new一个Form1窗体对象的方法,然后重载Form1窗体的构造函数来传递数据,因为Form1已经存在窗体一个对象,如果你再new一个Form1窗体对象。那就是一个新的Form1窗体了,不是原来那个Form1窗体了。 注意哦。每new一个对象就是一个新的窗体。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值