您的位置:时时app平台注册网站 > 编程知识 > C#底子:泛型委托时时app平台注册网站

C#底子:泛型委托时时app平台注册网站

2019-11-28 03:06

 

其实EventHandler<IntEventArgs>和EventHandler<StringEventArgs>是两个完全不同的委托,它们所指代的函数都分别有着不同的签名形式。请参见下面的示例:

.NET Framework中预定义的委托

前言:从.NET Framework2.0开始以来,系统预定义的委托使使代码看起来有点像“天书”,再加上匿名表达式,以及后面Lambda表达式的“掺和”,代码就更加难懂了,于是自己就一点点查MSDN,到现在终于有点入门了。
常用委托:
1、public delegate void Action<T>(T obj )
2、public delegate TResult Func<TResult>()
3、public delegate bool Predicate<T>(T obj) 
其中:Action和Func还包括从不带任何参数到最多四个参数的重载?

1、public delegate void Action<T>(T obj )
封装一个方法,该方法只采用一个参数并且不返回值。

时时app平台注册网站 1Code

2、public delegate TResult Func<TResult>()
封装一个具有一个参数并返回 TResult 参数指定的类型值的方法。
类型参数T
   此委托封装的方法的参数类型。
TResult
   此委托封装的方法的返回值类型

时时app平台注册网站 2Code
public static void Main()
   {
      // Instantiate delegate to reference UppercaseString method
      ConvertMethod convertMeth = UppercaseString;
      string name = "Dakota";
      // Use delegate instance to call UppercaseString method
      Console.WriteLine(convertMeth(name));
   }

   private static string UppercaseString(string inputString)
   {
      return inputString.ToUpper();
   }

3、public delegate bool Predicate<T>(T obj) 
表示定义一组条件并确定指定对象是否符合这些条件的方法。
类型参数
T:要比较的对象的类型。

返回值
如果 obj 符合由此委托表示的方法中定义的条件,则为 true;否则为 false。

时时app平台注册网站 3Code
 public static void Main()
    {
        // Create an array of five Point structures.
        Point[] points = { new Point(100, 200), 
            new Point(150, 250), new Point(250, 375), 
            new Point(275, 395), new Point(295, 450) };

        Point first = Array.Find(points, ProductGT10);

        // Display the first structure found.
        Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
    }

    // This method implements the test condition for the Find
    // method.
    private static bool ProductGT10(Point p)
    {
        if (p.X * p.Y > 100000)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

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

不过其中一些是 .net 4.0 里才有的,比如多个参数的 action


例子:

                    i ;
                    this.Invoke(new EventHandler(EndMessage), i);
                    //Action<int>
                    this.Invoke(new Action<int>(EndMessage2), i);//test action
                }//for 1

                //this.Invoke(new EventHandler(EndMessage), null);//new EventHandler(EndMessage) 是有可能被回收的,正规做法应当是用一个变量接收
                //不能将 null 传过去,为什么?
                this.Invoke(new EventHandler(EndMessage), 0);
            }
            catch (System.Exception ex)
            {
                
            }
            finally
            {
            }
        
        }//

        public void EndMessage2(int pos)
        {
        }//

        public void EndMessage(object sender, EventArgs e)
        {
            int i = (Int32)sender;
            if (i == 0)
            {
                MessageBox.Show("完成同步: " ls.Count);
            }
            else
            {
                if (ls != null && ls.Count > 0)
                progressBar_update.Value = 100 * i / ls.Count;
            }

            
        }//

 

就拿C#里最常见的委托EventHandler打比方。在.NET 2.0以前,也就是泛型出现以前,普通的事件处理函数都由EventHandler定义,如下:

               最近一直在研究委托与事件,下面是我的个人理解

  1. class IntEventArgs : System.EventArgs   
  2. {   
  3.     public int IntValue { get; set; }   
  4.     public IntEventArgs() { }   
  5.     public IntEventArgs(int value)    
  6.     { this.IntValue = value; }   
  7. }   
  8.   
  9. class StringEventArgs : System.EventArgs   
  10. {   
  11.     public string StringValue { get; set; }   
  12.     public StringEventArgs() { }   
  13.     public StringEventArgs(string value)    
  14.     { this.StringValue = value; }   
  15. }   
  16.   
  17. class Program   
  18. {   
  19.     static void PrintInt(object sender, IntEventArgs e)   
  20.     {   
  21.         Console.WriteLine(e.IntValue);   
  22.     }   
  23.   
  24.     static void PrintString(object sender, StringEventArgs e)   
  25.     {   
  26.         Console.WriteLine(e.StringValue);   
  27.     }   
  28.   
  29.     static void Main(string[] args)   
  30.     {   
  31.         EventHandler<IntEventArgs> ihandler =    
  32.             new EventHandler<IntEventArgs>(PrintInt);   
  33.         EventHandler<StringEventArgs> shandler =    
  34.             new EventHandler<StringEventArgs>(PrintString);   
  35.   
  36.         ihandler(null, new IntEventArgs(100));   
  37.         shandler(null, new StringEventArgs("Hello World"));   
  38.     }   
  39. }   

EventHandler 与常见的.Net预定义委托

看着下面这两句事件定义及激发忽然有点不明白了,

public event EventHandler<ExternalDataEventArgs> Submit;

Submit(null, args);

 

貌似该事件定义时只传一个参数args, 但实际激发时要传两个参数, 咋回事捏!

 

其实, 这是误解,  这个EventHandler<ExternalDataEventArgs>是个泛型版的预定义委托, 该委托实际的定义如下:

public delegate void EventHandler<TEventArgs> (
Object sender,
TEventArgs e
) where TEventArgs : EventArgs

而非泛型版的定义如下:

public delegate void EventHandler (

  Object sender,

  EventArgs e

)

这样就明白了, 事件确实是需要两个参数.

 

推荐资料: .NET Framework委托的预定义方法介绍

 

此文中这段甚对, "从.NET Framework2.0开始以来,系统预定义的委托使使代码看起来有点像“天书”,再加上匿名表达式,以及后面Lambda表达式的“掺和”,代码就更加难懂了."

因此,多梳理,多熟悉一下才行。

类似的预定义委托还有:

1.Action 封装1-16个参数, 无返回值.

public delegate void Action<in T>(
 T obj
)

public delegate void Action<in T1, in T2>(
 T1 arg1,
 T2 arg2
)

2.Func 封装1-16个参数, 返回值TResult.

public delegate TResult Func<out TResult>(

)

public delegate TResult Func<in T, out TResult>(
 T arg
)

3.Predicate 表示定义一组条件并确定指定对象是否符合这些条件的方法。

public delegate bool Predicate<in T>(
 T obj
)

 

推荐资料:

EventHandler 泛型委托
http://msdn.microsoft.com/zh-cn/library/db0etb8x(v=VS.80).aspx

Action<T> 委托

 

Func<TResult> 委托

 

Predicate<T> 委托
http://msdn.microsoft.com/zh-cn/library/bfcke1bz(v=VS.100).aspx


  1. public event EventHandler<BoliEventAgrs> BoliWaterEvent;
  2. EventHandler是系统自己的带参委托定义为:   public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
  3. BoliEventAgrs为委托参数,也是事件需要的参数;
  4. BoliWaterEvent为事件名字;
  5. 3.委托,参数,事件都有啦,下面就是写具体方法了,就是你的事件是什么事件,需要干啥的,
  6. 两步走,订阅也就是注册事件,执行触发事件的方法

    //注册 boli.BoliWaterEvent = boli1.Alarm; boli.BoliWaterEvent = boli1.Alarm1; //执行 boli.Boliwater();

有关泛型的具体特性与其在面向对象思想中的应用,将在后续与泛型相关的文章中重点阐述。

5.下面是完整代码

而.NET 2.0及其以后的版本,由于泛型的引入,所以一些内建(Built-in)的类、接口、委托都有了各自的泛型版本。EventHandler也不例外,它有了自己的泛型版本:EventHandler<T>,它的定义如下:

using System;

namespace DelegateEventObserver
{
    class Program
    {
        static void Main(string[] args)
        {
            a boli = new a();
            b boli1 = new b();
            boli.BoliWaterEvent  = boli1.Alarm;
            boli.BoliWaterEvent  = boli1.Alarm1;
            boli.Boliwater();
            Console.ReadKey();
        }
    }
    class BoliEventAgrs : EventArgs//继承系统事件参数接口
    {
        public readonly int tem;
        public BoliEventAgrs(int tem)
        {
            this.tem = tem;
        }
    }
    class a
    {
        //public delegate void Boli(object sender,BoliEventAgrs e);
        public event EventHandler<BoliEventAgrs> BoliWaterEvent;//BoliEventAgrs 为委托参数
        public void Boliwater()
        {
            for (int i=0; i<100;i  )
            {
                if (i>90)
                {
                    BoliEventAgrs e = new BoliEventAgrs(i);
                    if (BoliWaterEvent != null)
                    {
                        BoliWaterEvent(this, e);
                    }
                }
            }
        }
    }
    /// <summary>
    /// 委托方法,事件注册方法,参数e为 控制温度
    /// </summary>
    class b
    {
        public void Alarm(object sender,BoliEventAgrs e)
        {
            if (e.tem>95)
            {
                Console.WriteLine("水温{0}",e.tem);
            }
        }
        public void Alarm1(object sender, BoliEventAgrs e)
        {
            if (e.tem >98)
            {
                Console.WriteLine("水温{0},马上开啦", e.tem);
            }
        }
    }
}
  • EventHandler<IntEventArgs>指代这样一类函数:这些函数没有返回值,有两个参数,第一个参数是object类型,第二个参数是IntEventArgs类型
  • EventHandler<StringEventArgs>指代这样一类函数:这些函数没有返回值,有两个参数,第一个参数是object类型,第二个参数是StringEventArgs类型

时时app平台注册网站 4

泛型委托是委托的一种特殊形式,感觉看上去比较怪异,其实在使用的时候跟委托差不多,不过泛型委托更具有类型通用性。

4。效果

您应该可以发现,第二个参数的类型由EventArgs变成了TEventArgs,而TEventArgs具体是什么,则由调用方决定。假设IntEventArgs和StringEventArgs都继承于System.EventArgs,那么:

  • NOTE:参考了张子阳的思想,各位大佬可以看看
  • 1.事件要有委托,参数,事件
  • 2.委托可以自己定义:public delegate void  Boli(object sender,BoliEventAgrs e);
  • 也可以利用EventHandler进行操作,本次使用的是此方法:
  • 前提要声明参数(BoliEventAgrs),此类继承EventArgs而且是必须的;
    1 class BoliEventAgrs : EventArgs//继承系统事件参数接口
    2     {
    3         public readonly int tem;
    4         public BoliEventAgrs(int tem)
    5         {
    6             this.tem = tem;
    7         }
    8     }
    

view plaincopy to clipboardprint?

 

EventHandler指代了这样一类函数,这些函数没有返回值,并且有两个参数,第一个参数是object类型,而第二个参数是EventArgs类型。

view plaincopy to clipboardprint?

  1. public delegate void EventHandler(object sender, EventArgs e);  
  1. [Serializable]   
  2. public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e) where TEventArgs: EventArgs;  

view plaincopy to clipboardprint?

本文由时时app平台注册网站发布于编程知识,转载请注明出处:C#底子:泛型委托时时app平台注册网站

关键词: