Невозможно преобразовать тип с помощью преобразования ссылки, преобразования бокса, распаковки, преобразования упаковки или преобразования нулевого типа
в 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{}
}