Program.cs代码如下using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace Ch13.Ex02
{
    class Program
    {
        static void Main(string[] args)
        {
            Connection myConnection = new Connection();
            Display myDisplay = new Display();
            myConnection.MessageArrived += new MessageHandler(myDisplay.DisplayMessage);
            myConnection.Connect();
            Console.ReadKey();
        }
    }
}Connection.cs代码如下using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;namespace Ch13.Ex02
{
    public delegate void MessageHandler(string messageText);    public class Connection
    {
        public event MessageHandler MessageArrived;        private Timer pollTimer;        public Connection()
        {
            pollTimer = new Timer(100);
            pollTimer.Elapsed += new ElapsedEventHandler(CheckForMessage);
        }        public void Connect()
        {
            pollTimer.Start();
        }        public void Disconnect()
        {
            pollTimer.Stop();
        }        private static Random random = new Random();        private void CheckForMessage(object source, ElapsedEventArgs e)
        {
            Console.WriteLine("Checking for new messages.");
            if ((random.Next(9) == 0) && (MessageArrived != null))
            {
                MessageArrived("Hello Mum!");
            }
        }
    }
}Display.cs代码如下:using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace Ch13.Ex02
{
    public class Display
    {
        public void DisplayMessage(string message)
        {
            Console.WriteLine("Message arrived: {0}", message);
        }
    }
}问题如下:1.
初始化类的实例是不是就这种写法?
Connection myConnection = new Connection();
我看到很多程序都是先一个类名,再实例名=new 类名+一对小括号
2. 
myConnection.MessageArrived += new MessageHandler(myDisplay.DisplayMessage);
这句在P301看到有相关解释,在这里应该理解为:使用事件处理方法初始化的一个新委托实例,这个命令(使用略微古怪的语法,专用于委托)在列表中添加一个处理程序,当引发MessageArrived事件时,就会调用该处理程序。
2.1 新委托实例的实例名是啥?MessageHandler么?这个不是在Connection.cs里就定义了一个公共委托了么?
2.2 “在列表中添加一个处理程序”,列表在哪儿?
2.3 什么时候引发了MessageArrived事件了?怎么引发的?3.
为何要myConnection.Connect();来启动定时器?Connect函数里才一句话,如果直接让pollTimer变成public的,那就可以直接myConnection.pollTimer.Start()了吧?或者直接把定时器放Program.cs里,就可以不用调用myConnection实例里的timer了4.
第八章讲到构造函数的定义是:用于初始化数据的函数。是不是可以简单的理解为C语言中的所有变量声明,结构体共用体之类的定义都要放在类的构造函数中?在本例的Connection()这个构造函数中,
pollTimer.Elapsed += new ElapsedEventHandler(CheckForMessage);
4.1 这句话是不是只能放在构造函数里?
4.2
private static Random random = new Random();
public event MessageHandler MessageArrived;
private Timer pollTimer;
为何不放在构造函数里呢?这不是初始化一个random变量么?不是初始化生成实例么?
4.3 这类事件委托程序的写法里,new后面的ElapsedEventHandler是不是固定的?在P301的写到:“Timer对象有一个Elapsed事件,这个事件要求的事件处理程序必须匹配System.Timers.ElapsedHandler委托类型的返回类型和参数,是.NET Framework中定义的标准委托。”也就是说一种事件对应一种委托,所以代码写到=+时,按下tab就是默认的常用委托了?
4.4 这个委托的两个函数,Timer对象本身,ElapsedEventArgs对象的一个实例,都没在CheckForMessage函数里用到啊?是不是这类的委托函数的参数可以不用非得在函数体里调用?5.
关于MessageArrived("Hello Mum!");的
5.1 P304解释说这是用MessageHandler委托类型声明了一个MessageArrived事件,委托不是应该声明一个委托么?怎么委托声明了事件了?
5.2 这句话为啥可以直接给一个字符串参数就能输出了?MessageHandler类型的委托函数名也没有出现在MessageArrived后的括号里啊?他们是怎么和Display类里的输出函数相关联的?
谢谢各位的宝贵时间了!

解决方案 »

  1.   

    1 初始化类的实例是不是就这种写法?
    classname objname = new classname(构造函数的参数)
    2.1 新委托实例的实例名是啥?MessageHandler么?这个不是在Connection.cs里就定义了一个公共委托了么?myDisplay.DisplayMessage
    2.2 “在列表中添加一个处理程序”,列表在哪儿?这里指委托链
    2.3 什么时候引发了MessageArrived事件了?怎么引发的?这个要看类内部代码。
    3 作为简单程序,主要为了说明方法。
      

  2.   

    4 这句话是不是只能放在构造函数里?不一定
    为何不放在构造函数里呢?这不是初始化一个random变量么?不是初始化生成实例么?构造函数和初始化变量没有必然关系。
    也就是说一种事件对应一种委托,所以代码写到=+时,按下tab就是默认的常用委托了?
    事件和委托是多对1的关系。tab是IDE的功能而已。
    是不是这类的委托函数的参数可以不用非得在函数体里调用?是的。
    如同你写一个方法,未必一定要用到传入的参数。
    5 这个你看msdn里面C#编程指南关于委托的概念。仔细理解下。
      

  3.   

    1、正确
    2.1 新委托实例的实例名是啥?MessageHandler么?这个不是在Connection.cs里就定义了一个公共委托了么?
    MessageHandler是一种委托,这个委托在你的代码中有定义:
    public delegate void MessageHandler(string messageText);然后Connection类中,用这个委托定义了一个事件:
     public event MessageHandler MessageArrived;所以在代码中可以这样:
    myConnection.MessageArrived += new MessageHandler(myDisplay.DisplayMessage);将myConnection对象的MessageArrived事件处理程序指定为一个MessageHandler类型的处理程序:        public void DisplayMessage(string message)
            {
                Console.WriteLine("Message arrived: {0}", message);
            }
    这个程序的签名符合MessageHandler委托的定义2.2 “在列表中添加一个处理程序”,列表在哪儿?
    MessageArrived事件的处理程序可以有多个,依照给他+=的顺序依次被调用,所以这是一个委托列表
    2.3 什么时候引发了MessageArrived事件了?怎么引发的?        private void CheckForMessage(object source, ElapsedEventArgs e)
            {
                Console.WriteLine("Checking for new messages.");
                if ((random.Next(9) == 0) && (MessageArrived != null))
                {
                    MessageArrived("Hello Mum!");
                }
            }
    这里通过MessageArrived触发事件的。3.为何要myConnection.Connect();来启动定时器?Connect函数里才一句话,如果直接让pollTimer变成 public的,那就可以直接myConnection.pollTimer.Start()了吧?或者直接把定时器放Program.cs里,就可以不用调用myConnection实例里的timer了
    你的Connection对象是通过使用定时器来触发事件的,所以必须要启动定时器,否则都不会导致MessageArrived事件被触发,如果直接那样是可以的,但是类的设计要保证该公开的才公开,不能全部都是Public
    4.第八章讲到构造函数的定义是:用于初始化数据的函数。是不是可以简单的理解为C语言中的所有变量声明,结构体共用体之类的定义都要放在类的构造函数中?在本例的Connection()这个构造函数中,
    pollTimer.Elapsed += new ElapsedEventHandler(CheckForMessage);
    构造函数,是确保这个对象被New以后,内部的数据得到正确的初始化,以便能够供调用方正确使用,所以并不是你所理解的那样。
    4.1 这句话是不是只能放在构造函数里?
    另外:
    pollTimer.Elapsed += new ElapsedEventHandler(CheckForMessage);
    也不一定要防止构造函数里面,放在其他地方也可以,根据需要而已。
    4.2private static Random random = new Random();
    public event MessageHandler MessageArrived;
    private Timer pollTimer;
    为何不放在构造函数里呢?这不是初始化一个 random变量么?不是初始化生成实例么?
    首先不能在实例方法中定义静态变量,所以这个不可以。
    所以的构造函数只是确保对象能被外界使用之前,正确初始化一些状态信息,并不是所有的定义和初始化都要放在构造函数中。4.3 这类事件委托程序的写法里,new后面的ElapsedEventHandler是不是固定的?在P301的写到:“Timer对象有一个Elapsed 事件,这个事件要求的事件处理程序必须匹配System.Timers.ElapsedHandler委托类型的返回类型和参数,是.NET Framework中定义的标准委托。”也就是说一种事件对应一种委托,所以代码写到=+时,按下tab就是默认的常用委托了?
    不是固定的,正如这句话所说:
    “Timer对象有一个Elapsed 事件,这个事件要求的事件处理程序必须匹配System.Timers.ElapsedHandler委托类型的返回类型和参数,是.NET Framework中定义的标准委托。”
    必须是符合事件的委托,才可以这样。
    4.4 这个委托的两个函数,Timer对象本身,ElapsedEventArgs对象的一个实例,都没在CheckForMessage函数里用到啊?是不是这类的委托函数的参数可以不用非得在函数体里调用?
     pollTimer.Elapsed += new ElapsedEventHandler(CheckForMessage);Timer对象是为了定时调用CheckForMessage,它本身和ElapsedEventArgs对象,并不需要在CheckForMessage使用,这是肯定的,你要理解这里Timer对象是为了定时触发调用CheckForMessage
    5.
    关于MessageArrived("Hello Mum!");的
    5.1 P304解释说这是用MessageHandler委托类型声明了一个MessageArrived事件,委托不是应该声明一个委托么?怎么委托声明了事件了?
    委托可以理解成函数的签名,所谓函数的签名就是说这个函数返回什么类型的值,有什么类型的参数,有几个参数,事件是.NET提供的一种函数回调的封装,就是在某种情况发生时(这就是发生了某个事件),自动去调用一个方法,所以为一个事件添加处理程序是这样的:myConnection.MessageArrived += new MessageHandler(myDisplay.DisplayMessage);这里的MessageArrived 是事件,MessageHandler是一个委托类型,myDisplay.DisplayMessage是符合委托类型的一个函数,用于处理事件。
    5.2 这句话为啥可以直接给一个字符串参数就能输出了?MessageHandler类型的委托函数名也没有出现在MessageArrived后的括号里啊?他们是怎么和Display类里的输出函数相关联的?
    这里的 MessageArrived("Hello Mum!");等于是触发了一个事件,这回导致DisplayMessage函数被执行,“Hello Mum!”被传送到该函数进行输出。