简单的说明c#委托的作用
2018-09-12 11:16:17 weixin_42290878 阅读数 90

1.委托(其中一种写法):
一个委托包含以下的方法1和方法2,一个方法1可对应多个方法2,方法2相当于参数,在实际调用的时候写入不同的方法名即可
方法1:方法名(Action <参数1类型,参数2类型…>回调),方法1声明所委托方法的参数类型,方法1还应包含调用方法2的语句callback?.Invoke(参数1,参数2 …)

方法2:方法名(参数类型参数1,参数类型参数2 …)其中参数必须与方法1数量相同,对应类型相同

实际调用:在已经实现了方法1和方法2的前提下:方法1(方法2);
这种写法的委托,一旦实际调用,会马上进入方法1,执行方法1的过程中会调用方法2(callback),参数由方法1提供。

以下为试验代码(输出99乘法表):
//方法1

MultiplicationTable(Action <int, int> callback)
        {
            for(int i = 1; i<= 9; i++)
            {
                for(int j = i; j <= 9; j++)
                {
                    callback?.Invoke(i, j);
                }
                Console.WriteLine();
            }
        }
     

//方法2

PrintMultiplicationTable(int a, int b)
        {
            Console.Write(a + " * " + b + " = " + (a * b).ToString().PadRight(2,' ')+" ");
        }

//实际调用:注意实际使用中可能要在方法1跟方法2前面加上类名或者对象名称,这取决于你的方法1跟方法2

MultiplicationTable(PrintMultiplicationTable);

总结:委托实际上等于将方法2当做一个方法1的参数,Action相当于方法2的“类名”

2018-10-21 12:50:00 weixin_34023863 阅读数 40

C# 委托和事件,简单示例说明问题

 

先看看示例效果

按照国际惯例,得先说说概念。

委托(C# 编程指南)

事件(C# 编程指南)

以上内容来自MSDN。

委托源码

【委托】

概念和代码都有了。剩下的就是应用了,要是只知道概念不会用,那还是等于不会。

要用委托首先要明确几个问题:

1、为什么需要委托?什么场合用?

  我也不想使用委托,谁没事想多些代码。但是在某一天,我写代码的时候,在多线程中访问了 UI 控件,发现不行。于是乎百度一大堆,结果就是用委托。官方也有这样的Demo,具体自己百度。于是乎得到一个答案,多线程访问 UI 控件得借助委托。其他的场景不说了,其实大部分都是多线程和异步的场景需要。到这里我们就明白了,委托这东西,可以在多线程或者异步操作中发挥大作用,可以在窗体间传参,而且还很安全。

2、怎么使用? 

  委托的使用也是比较容易的。

  1)、定义委托

  2)、声明委托对象

  3)、实例化委托

  4)、调用委托(执行方法)

来点实际的代码,多线程中访问 UI 控件:

复制代码
public delegate void UpdateTextEventHandler(string strText); // 1、定义委托类型

        public UpdateTextEventHandler UpdateText; // 2、声明委托对象public FrmMain()
        {
            InitializeComponent();

            UpdateText = OnUpdateText; // 3、实例化委托对象,这里编译后就不是这样子了,而是有个 new 操作
        }

        private void OnUpdateText(string strText)
        {
            labTest.Text = strText;
        }

        private void btnThreadOperateControl_Click(object sender, EventArgs e)
        {
            new Task(() =>
            {
                // 这里就不得不使用委托了,否则会报错,提示大概意思就是“不能再其他线程访问控件"
                for (int i = 0; i < 1000; i++)
                {
                    // 自定义委托方式
                    //Invoke(UpdateText, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));

                    // 采用泛型委托简化后
                    Invoke(new Action<string>(strText => labTest.Text = strText), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));

                    System.Threading.Thread.Sleep(10);
                }
            }).Start();
        }
复制代码

以上代码比较简单,但可以解决一些基本的多线程访问控件问题。现实场景有:后台多线程操作业务,打印操作日志到主界面Text框。后台采集数据,更新到主界面Chart。

当然,委托作为C#的一个很核心的东西,远不止这些内容。有多播委托,将委托作为函数参数进行封装等。

委托类似:c/c++中的函数指针封装版,MFC/C++Builder中的PostMessage/SendMessage封装版,Qt中的信号槽。

 

一道华丽的分割线


 

【事件】

使用事件也要弄清楚几个问题

1、为什么使用委托?什么场合用?

  事件是对多播委托的一个封装,主要是限制谁发布事件,谁触发。比如自己定义一个类,类里面有个事件,那么只能你来触发,响应在别人那边。事件多用于UI操作,但不代表非UI不可以使用。窗体程序将这一点体现的淋漓尽致。

2、怎么使用?

  事件的使用也是比较容易的。

  1、由于事件是基于委托的,那么你得先定义一个委托类型

  2、声明委托对象,并用event关键字修饰

  3、在声明事件的类内部使用(谁声明的,谁触发)

  4、在声明事件的类的外部绑定(没有声明的,那你就来订阅(绑定 +=)事件)

 

来点实际代码:

复制代码
using System;

namespace EventDemo
{
    public delegate void TestEventHandler();

    class Program
    {
        static void Main(string[] args)
        {
            Class1 class1 = new Class1();
            class1.Test1 = Test;
            // 委托调用,这里代表是Program类调用class1.Test1(),可不能理解成class1调用
            class1.Test1();

            class1.Test += Test;
            // 事件调用,这里对事件的体现不是很明显,因为能看到调用了DoSomething。
            // 虽然调用了DoSomething,但是事件是在Class1内部调用的
            class1.DoSomething();

            Console.WriteLine("Press any key to close the application...");
            Console.ReadKey(true);
        }

        static void Test()
        {
            Console.WriteLine("hello world.");
        }
    }

    class Class1
    {
        public TestEventHandler Test1; // 声明委托对象

        public event TestEventHandler Test; // 声明事件对象

        public void DoSomething()
        {
            Test?.Invoke();
        }

    }

}
复制代码

 

个人经验分享2句话区分委托和事件:

1、委托一般是自己声明,别人调用。

2、事件是自己声明,自己调用,但是响应在别人那边。

 

看完了这些,不要以为你就会使用委托和事件,只能说明你看了我的文章,谢谢。

demo

2015-06-08 09:11:04 zj735539703 阅读数 287

泛型:即通过参数化类型来实现在同一份代码上操作多种数据类型。泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。

C#泛型的作用概述

C#泛型赋予了代码更强的类型安全,更好的复用,更高的效率,更清晰的约束。

在一个方法中,一个变量的值是可以作为参数,但其实这个变量的类型本身也可以作为参数。泛型允许我们在调用的时候再指定这个类型参数是什么。在.net中,泛型能够给我们带来的两个明显的好处是–类型安全和减少装箱、拆箱。

假设我们现在有一个人员集合:创建Person类

 public class Person  
    {  
    private string name;  
    private int age;  

    public Person(string Name, int Age) //构造函数  
    {  
    this.age = Age;  
    this.name = Name;  
    }  
    public string Name  
    {  
    set { this.name = value; }  
    get { return name; }  
    }  
    public int Age  
    {  
    set { this.age = value; }  
    get { return age; }  
    }  
    } 

//我们在程序的入口点处运行 以下在集合中增加了一个其他类型的对象,但插入数据的时候并没有报错,编译也可以通过,但把“谁是功夫之王?”这样的字段转换成人员的时候出问题了,这说明ArrayList是类型不安全的。

 static void Main(string[] args)  
    {  
    ArrayList peoples = new ArrayList();  
    peoples.Add(new Person("成龙", 18));  
    peoples.Add(new Person("李小龙", 17));  
    peoples.Add("谁是功夫之王?");  
    foreach (Person person in peoples)  
    {  
    Console.WriteLine(person.Name + "今年" + person.Age + "岁。");  
    }  
    } 

//因此在此处中我们创建一个人员的泛型,当要向里面插入其他类型的时候,编译器就会报错

  static void Main(string[] args)  
    {  
    List< Person> peoples = new List< Person>();  
    peoples.Add(new Person("成龙", 18));  
    peoples.Add(new Person("李小龙", 17));  
    peoples.Add("谁是功夫之王?");  
    foreach (Person person in peoples)  
    {  
    Console.WriteLine(person.Name + "今年" + person.Age + "岁。");  
    }  
    } 

C#泛型的作用:排序

C#泛型作为一种集合,排序是不可或缺的。排序基于比较同,要排序,首先要比较。一个对象可以有多个比较规则,但只能有一个默认规则,默认规则放在定义该对象的类中。默认规则在CompareTo方法中定义,该方法属于IComparable< T>泛型接口。

 public class Person :IComparable< Person>   
    {  

    。。。。。。  
    public int CompareTo(Person p) //此处增加一个按年龄排序比较器  
    {  
    return this.Age - p.Age;  
    }  
    }  

    static void Main(string[] args)  
    {  
    List< Person> peoples = new List< Person>();  
    peoples.Add(new Person("陈小龙", 18));  
    peoples.Add(new Person("李小龙", 17));  
    peoples.Add(new Person("房小龙", 23));  
    peoples.Add(new Person("张小龙", 42));  
    peoples.Sort(); //不带参数的Sort()方法对集合进行排序  
    foreach (Person person in peoples)  
    {  
    Console.WriteLine(person.Name + "今年" + person.Age + "岁。");  
    }  
    } 
2018-07-09 15:20:43 m0_37863265 阅读数 655
现有这样的一个类:
class TestRunTime{
    static string s;
    static void Main(string[] args){
         
    }
    private static void todo1(){
        for (int i = 0; i < 10000; i++){
            s += "1";
        }
    }
    private static void todo2(){
        for (int i = 0; i < 10000; i++){
            s += "2";
        }
    }
}

如果我们想要计算todo1()和todo2()方法的运行时间,一般我们可以这样写:

class TestRunTime{
    static string s;
    static void Main(string[] args){
        Runtime();
        Console.ReadKey(); 
    }
    private static void Runtime(){//计算方法运行时间
        DateTime beforDT, afterDT;
        TimeSpan ts;
       
        beforDT = System.DateTime.Now;
        todo1();//todo1方法
        afterDT = System.DateTime.Now;
        ts = afterDT.Subtract(beforDT);
        Console.WriteLine("总共花费{0}ms.", ts.TotalMilliseconds);

        beforDT = System.DateTime.Now;
        todo2();//todo2方法
        afterDT = System.DateTime.Now;
        ts = afterDT.Subtract(beforDT);
        Console.WriteLine("总共花费{0}ms.", ts.TotalMilliseconds);
    }
    private static void todo1(){}
    private static void todo2(){}
}

这样写的话我们就可以分别计算出这两方法运行的时间,但是这样写非常不好,不易于拓展。如果我们需要求其他方法的运行时间,需要修改大量代码,非常不友好。

于是此时需要我们运用委托的知识对计算这个方法进行修改,更改之后代码是这样的:

    class TestRunTime{
        public delegate void Func();//声明委托
        static string s;
        static void Main(string[] args){
            Console.WriteLine("总共花费{0}ms.",Runtime(todo1));
            Console.WriteLine("总共花费{0}ms.", Runtime(todo2));
            Console.ReadKey(); 
        }
        private static double Runtime(Func fc){
            DateTime beforDT, afterDT;
            TimeSpan ts;

            beforDT = System.DateTime.Now;
            fc();//耗时巨大的代码
            afterDT = System.DateTime.Now;
            ts = afterDT.Subtract(beforDT);

            return ts.TotalMilliseconds;
        }
        private static void todo1(){}
        private static void todo2(){}
    }

这样写的话,如果需要对任意方法求运行时间,只需要把任意方法作为参数传入Runtime(Func func)方法,即可返回运行时间。

从以上例子我们可以发现委托的作用:

它可以将方法作为另一个方法的参数进行传递。




2016-03-03 21:35:17 qq_15572445 阅读数 216
this.Invoke(new Action(() =>
{
    //这里面写需要进行的委托操作
    //比如线程操作界面的语句等
}));




//举例
this.Invoke(new Action(() =>
{
    this.TextBox1.Text = "12345";
}));


//举例
this.Invoke(new Action(() =>
{
    this.ListBox1.SelectedIndex = 0;
}));

c#委托_01_简单委托的构成

阅读数 22

为了让委托做某事,必须满足4个条件:  •声明委托类型;  •必须有一个方法包含了要执行的代码;  •必须创建一个委托实例;  •必须调用(invoke)委托实例。1.声明委托类型      delegatevoidStringProcessor(stringinput);2.为委托实例的操作找到一个恰当的方法      ...

博文 来自: weixin_33981932

C# 委托的简单应用

阅读数 13

delegate是委托的关键字委托的声明指定了一个函数名,其中包含了一个返回类型和参数列表。在定义了委托后,就可以声明该委托类型的变量。接着把这个变量初始化与委托相同建明的函数引用。之后,就可以使用委托变量调用这个函数了。就像该变量是一个函数一样有了引用函数的变量后,还可以执行不能用的其他方式完成的操作下面就举一个简单的例子,来看看C#是怎么操作的 usingSystem;usi...

博文 来自: chenhailong118

C#简单的委托案例

阅读数 533

在朋友的代码上修改的,在此感谢我的朋友---邓建军 publicdelegateintCompareDelegate(objectmax,objectobj);  classProgram  {    staticvoidMain(string[]args)    {      Console.WriteLine(Ge

博文 来自: zhang_z_qiang

c#委托的简单学习

阅读数 134

usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespaceConsoleApplication1{  classProgram  {    //普通委托    delegatevoidweituo()

博文 来自: qq_38204686

C#委托简单详解

阅读数 16

声明委托在C#中使用一个类分两个阶段,首选定义这个类,告诉编译器这个类由什么字段和方法组成的,然后使用这个类实例化对象。在我们使用委托的时候,也需要经过这两个阶段,首先定义委托,告诉编译器我们这个委托可以指向哪些类型的方法,然后,创建该委托的实例。定义委托的语法如下:delegatevoidIntMethodInvoker(intx);这个委托指向的方法是带有Int类型的参数,且方法...

博文 来自: qq_42108132
没有更多推荐了,返回首页