Пожалуйста, проверьте следующие сегменты кода:
public interface ICountable { }
public class Counter<T>
where T : ICountable
{
public int Count(IEnumerable<T> items)
{
return 0;
}
public int Count(T Item)
{
return 0;
}
}
public class Counter
{
public int Count<T>(IEnumerable<T> items)
where T : ICountable
{
return 0;
}
public int Count<T>(T Item)
where T : ICountable
{
return 0;
}
}
Две версии счетчика отличаются только спецификацией общего параметра. Один из них определяет как типичный параметр типа, другой - как общий аргумент. Оба ограничивают аргументы метода для реализации интерфейса ICountable. Я буду называть их конкретными и неспецифическими соответственно.
Теперь я определяю класс, который реализует интерфейс ICountable, и набор экземпляров:
public class CItem : ICountable { }
var countables = new List<CItem>();
Затем я хотел бы использовать оба класса Counter в коллекции.
var specific = new Counter<CItem>();
var nonspecific = new Counter();
specific.Count(countables);
nonspecific.Count(countables);
Конкретный счетчик распознает, что коллекция счетчиков должна попадать в подпись int Count (IEnumerable), но неконкретная версия этого не делает. Я получаю сообщение об ошибке:
Тип '
System.Collections.Generic.List<CItem>
' не может использоваться как тип типаT
'в общем типе или методеCounter.Count<T>(T)
. Нет никакого неявного преобразования ссылок изList<CItem>
'доICountable
.
Похоже, что неспецифическая версия использует неправильную подпись для коллекции.
Почему они ведут себя по-другому? Как указать конкретную версию, чтобы вести себя так же, как и другая?
Примечание. Я знаю, что этот пример нереалистичен. Однако я столкнулся с этой проблемой в довольно сложном сценарии с методами расширения. Я использую эти классы для простоты
Заранее спасибо