2010-04-26 27 views
2

以下代码似乎多次执行FileRetrieved事件。我认为代表是一个参考类型。我期待这个执行一次。我将采取猜测,说参考被按值传递,因此复制,但我不喜欢猜测:-)委托是否在分配给事件期间被复制?

public delegate void DirListEvent<T>(T dirItem); 

void Main() 
{ 
    DirListEvent<string> printFilename = s => { 
     Console.WriteLine (s); 
    }; 

    var obj = new DirectoryLister(); 

    obj.FileRetrieved += printFilename; 
    obj.FileRetrieved += printFilename; 

    obj.GetDirListing(); 
} 

public class DirectoryLister { 

    public event DirListEvent<string> FileRetrieved; 


    public DirectoryLister() { 
     FileRetrieved += delegate {}; 
    } 

    public void GetDirListing() { 

     foreach (var file in Directory.GetFiles(@"C:\")) 
     { 
      FileRetrieved(file); 
     } 
    } 
} 
+3

老实说,我不明白“委托是否是引用类型”应该以任何方式连接到“被执行一次”。您已经使用事件处理程序注册了相同的委托两次,因此它被调用了两次 - 为什么不呢? – 2010-04-26 07:36:36

回答

0

基本上,每个委托实例都带有一个调用列表,它基本上只是您关联的目标事件的所有引用的列表。例如,

public event DirListEvent<string> FileRetrieved; 

上面的代码创建一个名为FileRetrieved的委托类型(如您所知)。 现在,此委托类型具有一个调用列表,用于保存使用+ = operator或Delegate.Combine方法注册的所有委托实例。

obj.FileRetrieved += printFilename; 
obj.FileRetrieved += printFilename; 

该代码基本上将2个相同的委托实例添加到FileRetrieved调用列表中。 调用列表允许重复的实例。因此,调用FileRetrieved时,它会遍历其调用列表,并发现添加了两个方法(均为printFilename),并将调用委托给printFilename,就像它应该做的那样。

尝试使用另一行obj.FileRetrieved += printFilename;,并且FileRetrieved应该调用printFilename 3次。

3

实际上,FileRetrieved为代表的集合,和相同委托可以多次出现在这个集合中。并非所有集合都是集合...

+0

正确,'obj.FileRetrieved'结束包含对同一个委托的多个引用。 – 2010-04-26 08:09:43