Если я вас правильно понял, у вас есть интерфейс, который предоставляет несколько методов, каждый из которых принимает в основном один и тот же тип делегата, но получает входной параметр другого типа. Примерно так:
GetListOfSongs(..., delegate(List<Song> result) { ... });
GetListOfMovies(..., delegate(List<Movie> result) { ... });
а вы беспокоитесь о сигнатурах делегатов, которые начинают появляться вместе с методами в интерфейсе?
Если это так, то вам нужны дженерики. Фактически, если ваша подпись делегата соответствует моему примеру - то есть принимает один входной параметр, не возвращает значения - требуемый тип делегата уже существует в BCL. Это называется Action<T>
. Вы можете объявить методы, описанные выше, так:
GetListOfSongs(..., Action<List<Song>> callback);
GetListOfMovies(..., Action<List<Movie>> callback);
и у вас все равно будет только один тип делегата, то есть Action<T>
.
Теперь, если вам нужно передать более одного параметра, вы все равно охвачены. Существуют версии Action для 16 входных параметров (хотя их сигнатуры начинают выглядеть немного странно: Action<T1, T2, T3 ...>
).
Если вы хотите, чтобы ваш обратный вызов также возвращал значение, которое вы будете использовать где-то в вашей инфраструктуре, Func<T, TResult>
- ваш друг (T - тип входного параметра, TResult - тип значения, которое вы будете возвращать делегат).
В качестве бонуса я бы порекомендовал вам не выставлять List<T>
в своих интерфейсах. Если вы действительно думаете, что все ваши клиенты будут нуждаться в операциях со списком, используйте IList<T>
, но рассмотрите ICollection<T>
или даже IEnumerable<T>
, если они не будут.