Ответ 1
Вы можете сделать свой AddEntries
общий и изменить его на
void AddEntries<T>(List<T> test) where T : Foo
{
//your logic
}
Посмотрите Ограничения на параметры типа для получения дополнительной информации.
У меня есть такая настройка:
abstract class Foo {}
class Bar : Foo {}
и метод в другом месте этой формы:
void AddEntries(List<Foo>) {}
Я пытаюсь вызвать этот метод, используя список объектов типа Bar
List<Bar> barList = new List<Bar>()
AddEntries(barList);
но это дает мне ошибку:
не может преобразовываться из списка <Bar> для списка <Foo>
Во всяком случае, вокруг этой проблемы? Мне нужно сохранить определение метода с помощью абстрактного класса.
Вы можете сделать свой AddEntries
общий и изменить его на
void AddEntries<T>(List<T> test) where T : Foo
{
//your logic
}
Посмотрите Ограничения на параметры типа для получения дополнительной информации.
Прочитайте Ковариацию и контравариантность в generics от docs.microsoft.com, как это, в частности, раздел "Общие интерфейсы с параметрами ковариантного типа" будет охватывать сценарий, с которым вы работаете.
Короче говоря, если вы (можете) изменить подпись вашего метода AddEntries
на:
static void AddEntries(IEnumerable<Foo> entries)
(Обратите внимание на использование IEnumerable<Foo>
вместо List<Foo>
), вы сможете делать то, что вы хотите сделать.
Конкретная разница здесь в том, что IEnumerable<T>
и List<T>
объявляются по-разному:
public interface IEnumerable<out T> : IEnumerable
public class List<T> : IList<T>, ... ...
Разница, которая имеет значение, - это out
в объявлении IEnumerable<T>
, которая указывает, что она ковариантна, что означает (с определением, взятым с docs.microsoft.com):
Ковариация. Позволяет использовать более производный тип, чем первоначально указано.
Это запрещено по простой причине. Предположим, что ниже компилируется:
AddEntries(new List<Bar>());
void AddEntries(List<Foo> list)
{
// list is a `List<Bar>` at run-time
list.Add(new SomethingElseDerivingFromFoo()); // what ?!
}
Если ваш код будет скомпилирован, у вас есть небезопасное дополнение (что делает бессмысленные общие списки), где вы добавили SomethingElseDerivingFromFoo
на самом деле List<Bar>
(тип времени выполнения).
Чтобы решить вашу проблему, вы можете использовать generics:
void AddEntries<T>(List<T> list) where T:Foo
{
}