Невозможно преобразовать тип с помощью преобразования ссылки, преобразования бокса, распаковки, преобразования упаковки или преобразования нулевого типа

в C#, если у меня есть параметр для функции, где тип параметра имеет интерфейс, как сделать проход в объекте, который реализует интерфейс.

вот пример:

параметр для функции выглядит следующим образом:

List<ICustomRequired>

список, который у меня уже есть следующее:

List<CustomObject> exampleList

CustomObject наследует от ICustomRequired интерфейс

каков правильный синтаксис для передачи exampleList как параметр?

вот как я думал сделать выше задач:

exampleList as List<ICustomRequired>

однако я получаю следующую ошибку:

не удается преобразовать тип через преобразование ссылки, преобразование бокса, преобразования распаковывания, оборачивая преобразования, или null тип преобразования

спасибо

3 ответов


вы не можете бросить List одного типа List другого типа.

и если вы думаете об этом, вы были бы рады, что не можете. Представьте себе, какой хаос вы могли бы вызвать, если бы это было возможно:

 interface ICustomRequired
 {
 }

 class ImplementationOne : ICustomRequired
 {
 }

 class ImplementationTwo: ICustomRequired
 {
 }

 var listOne = new List<ImplementationOne>();
 var castReference = listOne as List<ICustomRequired>();
 // Because you did a cast, the two instances would point
 // to the same in-memory object

 // Now I can do this....
 castReference.Add(new ImplementationTwo());

 // listOne was constructed as a list of ImplementationOne objects,
 // but I just managed to insert an object of a different type

обратите внимание, однако, что эта строка кода является законной:

 exampleList as IEnumerable<ICustomRequired>;

это было бы безопасно, потому что IEnumerable не предоставляет никаких средств для добавления новых объектов.

IEnumerable<T> фактически определяется как IEnumerable<out t>, что означает параметр типа ковариантные.

вы можете изменить параметр функции IEnumerable<ICustomRequired>?

в противном случае ваш единственный вариант-создать новый список.

var newList = (exampleList as IEnumerable<ICustomRequired>).ToList();

или

var newList = exampleList.Cast<ICustomRequired>().ToList();

вы не можете этого сделать, вы должны преобразовать list

exampleList.Cast<ICustomRequired>().ToList();

на List.Cast, дженерики C#обеспечивают хорошую поддержку ковариация и контравариация. Этот пример заставляет его работать так, как я думаю, вы изначально намеревались.

public class Program
{
    public static void Main()
    {
         Foo(new List<Fim>());
    }

    public static void Foo<T>(List<T> bar) where T : IFim
    {
        throw new NotImplementedException();
    }

    public class IFim{}
    public class Fim : IFim{}
}