2010-01-23 6 views
4

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

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); 

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

Благодаря

ответ

1

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

+0

Я не уверен, поможет ли здесь разница. 'EventHandler <>' инвариантно определен в .NET. – nawfal

1

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

0

В общем объявлении делегата можно указать, что определенные параметры типа должны быть ковариантными или контравариантными, что позволит использовать типы назначений. К сожалению, внутренняя реализация делегатов многоадресной рассылки делает невозможным объединение делегатов разных типов («простой» делегат содержит информацию о своем типе, указатель метода и ссылку на его цель; многоадресная информация делегата о ее типе наряду с содержит указатели на методы и целевые ссылки для каждого из своих составных делегатов, но не содержит ссылки на исходных делегатов, которые были объединены, и не содержит никакой информации об их типах). Таким образом, попытка совместить 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> не сможет выполнить компиляцию, даже если действие может быть успешным, если это была единственная подписка.

Смежные вопросы