Копируются ли делегаты во время назначения на событие? - PullRequest
2 голосов
/ 26 апреля 2010

Следующий код, кажется, выполняет событие 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);
        }
    }
}

Ответы [ 2 ]

3 голосов
/ 26 апреля 2010

По сути, FileRetrieved является коллекцией делегатов, и один и тот же делегат может появляться в этой коллекции несколько раз. Не все коллекции являются наборами ...

0 голосов
/ 26 апреля 2010

По сути, каждый экземпляр делегата поставляется со списком вызовов , который, по сути, является просто списком всех ссылок на целевые события, с которыми вы связываетесь. Например,

public event DirListEvent<string> FileRetrieved;

код выше создает тип делегата с именем FileRetrieved (как вы уже знаете). Этот тип делегата теперь имеет список вызовов, в котором хранятся все экземпляры делегатов, которые вы зарегистрировали с помощью оператора + = или метода Delegate.Combine.

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

Этот код в основном добавляет 2 одинаковых экземпляра делегата в список вызовов FileRetrieved. Список вызовов допускает дублирование экземпляров. Следовательно, когда вызывается FileRetrieved, он просматривает свой список вызовов и обнаруживает, что добавлено 2 метода (оба printFilename), и просто делегирует вызовы printFilename, как и предполагалось .

Попробуйте использовать еще одну строку obj.FileRetrieved += printFilename;, и FileRetrieved должен вызвать printFilename 3 раза.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...