Как объявить общее событие для общего делегата в С#

У меня есть пользовательский элемент управления, который имеет дело с файловой загрузкой. Я определил делегата следующим образом

public delegate void FileUploadSuccess<T>(T value,FileUploadType F)

Значение может быть как строкой, так и байтовым массивом. FileUploadType - это перечисление, которое сообщает, какой тип файла был загружен.

Теперь я объявил событие в usercontrol, чтобы поднять это.

public event FileUploadSuccess<string> successString;   //In case I want a file name

public event FileUploadSuccess<Byte[]> successStringImage;  // In case I want a byte[] of uploaded image

То, что я хотел, было общим событием

public event FileUploadSuccess<T> successString. 

Ответ 1

За исключением части общих типов (т.е.

class Foo<T> { public event SomeEventType<T> SomeEventName; }

) нет таких вещей, как общие свойства, поля, события, индексы или операторы (только общие типы и общие методы). Может ли содержащийся тип быть общим?

Ответ 2

Для внешнего мира событие во многих отношениях выглядит как поле класса. Так же, как вы не можете использовать открытый родовой тип для объявления поля, вы не можете использовать открытый общий тип для объявления события.

Если вы можете оставить тип открытым, компилятор должен будет скомпилировать в обработчике события добавление и удаление кода для каждого возможного типа для вашего общего параметра T. Закрытый общий тип не может быть скомпилирован JIT, потому что ваше событие не является типом в своем собственном праве, а является частью закрывающего типа.

Ответ 3

Это невозможно, если вы не определяете свой параметр типа в окружающем классе. Например:

public delegate void FileUploadSuccess<T>(T value, FileUploadType F)

public class FileUploader<T>
{
    public event FileUploadSuccess<T> FileUploaded;
}

Но это только переносит вашу проблему в другое место, так как теперь вам придется объявить два экземпляра класса FileUploader:

FileUploader<string> stringUploader = new FileUploader<string>();
FileUploader<byte[]> stringUploader = new FileUploader<byte[]>();

Возможно, это не то, что вы хотите.

Ответ 4

Зачем вам нужно общее событие? Не можете ли вы просто использовать обычное событие:

public delegate void FileUploadSuccess(object value);

а затем

public event FileUploadSuccess Success;

В обработчике события Success вы узнаете тип передаваемого объекта:

public void SuccessHandler(object value)
{
    // you know the type of the value being passed here
}

Ответ 5

Я не думаю, что это возможно.

Событие похоже на экземпляр делегата (грубо говоря), а экземпляр представляет собой конкретную реализацию (общего или не общего класса).

Для лучшего понимания делегатов и событий вы можете обратиться к обсуждению этого SO.