Гетерогенный список делегатов - PullRequest
4 голосов
/ 23 января 2010

Можно ли создать список, содержащий делегатов разных типов? Например, рассмотрим два делегата:

class MyEventArg1 : EventArgs {}
class MyEventArg2 : EventArgs {}

EventHandler<MyEventArgs1> handler1;
EventHandler<MyEventArgs2> handler2;

Я бы хотел сделать что-то подобное:

List<EventHandler<EventArgs>> handlers = new List<EventHandler<EventArgs>>();

handlers.Add((EventHandler<EventArgs>)handler1);
handlers.Add((EventHandler<EventArgs>)handler2);

Но приведение от одного делегата к другому кажется невозможным. Моя цель - сохранить делегатов в списке, чтобы не вызывать их; но просто чтобы автоматически отменить их регистрацию.

Спасибо

Ответы [ 3 ]

1 голос
/ 23 января 2010

Да, это не работает, делегаты совершенно не связаны между собой. Обычно универсальные типы имеют только System.Object в качестве общего базового типа. Но здесь, поскольку они являются делегатами, вы можете хранить их в List<Delegate>. Я сомневаюсь, что это поможет вам получить их незарегистрированными. Но я не могу представить, как может выглядеть этот код.

1 голос
/ 23 января 2010

Вы сможете сделать это в C # 4.0 благодаря универсальной дисперсии , но до тех пор вам нужно найти другой способ (возможно, ArrayList ).

0 голосов
/ 13 декабря 2012

В объявлении общего делегата можно указать, что определенные параметры типа должны быть ковариантными или контравариантными, что позволит использовать типы назначений, которые вы ищете. К сожалению, внутренняя реализация многоадресных делегатов делает невозможным объединение делегатов разных типов («простой» делегат содержит информацию о своем типе вместе с указателем метода и ссылкой на его цель; информация о его типе многоадресного делегата вместе с содержит указатели на метод и целевые ссылки для каждого из составляющих его делегатов, но не содержит никаких ссылок на исходные делегаты, которые были объединены, а также не содержит никакой информации об их типах). Таким образом, попытка объединить EventHandler<DerivedEventArgs> с EventHandler<EventArgs> потерпит неудачу во время выполнения.

Если бы EventHandler<T> было контравариантным по отношению к T, попытка передать EventHandler<EventArgs> стандартному методу AddHandler события, которое предполагает компиляцию EventHandler<DerivedEventArgs>, и даже была бы успешной, если бы не было других обработчиков. подписался, поскольку EventHandler<EventArgs> будет Delegate.Combine d с null, таким образом, сохраняясь в поле делегата события как EventHandler<EventArgs>. К сожалению, последующая попытка добавить EventHandler<DerivedEventArgs> (который на самом деле является ожидаемым типом) потерпит неудачу, поскольку его тип не соответствует делегату, с которым он комбинируется. Microsoft решила, что такое поведение нарушит принцип наименьшего удивления (если передача «неправильного» делегата вызовет какие-либо проблемы, она должна делать это при передаче этого делегата, а не при передаче более позднего), и решила минимизировать вероятность сценария, сделав так, что попытка передать EventHandler<EventArgs> обработчику, который ожидает, что EventHandler<DerivedEventArgs> завершится компиляцией, даже если действие могло завершиться успешно, если бы это была единственная подписка.

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