2016-11-03 3 views
1

Я хочу передать список объектов конструктору NavigationPage, чтобы я мог заполнить содержимое ListView на этой странице.C# как передать список объектов конструктору?

объекты будут разными типами, которые все наследуемые от того же родителя, который является абстрактным класс называется «Animal» определяется следующим образом:

abstract class Animal { ... 

унаследованных классов, как это:

public class Horse : Animal { ... 

public class Cow : Animal { ... 

public class Dog : Animal { ... 

страница, которая отображает этот список является класс наследуется от NavigationPage следующим образом:

public List<Animal> Animals = new List<Animal>(); 

    public AnimalListPage(string title, List<Animal> animals) { 
    .... 

и я создаю объект AnimalListPage следующим образом:

var horses = new List<Horse>() { 
    new Horse("Silver", 65, 70), 
    new Horse("Tucker", 60, 68) 
}; 
horsesListPage = new AnimalListPage("Horses", horses); 
.... 

EDIT: в ответ на некоторые из предложений; Чтобы уточнить: мне нужно сохранить тип объекта «Лошадь», «Корова», «Собака» и т. Д. В списке, потому что каждый тип Animal имеет уникальные атрибуты для отображения. Кроме того, каждый экземпляр списка животных будет иметь только один тип, т. Е. Никогда не будет списка, объединяющего Лошадей, Коровы и Собаки.

Но я получаю ошибку:

Error CS1503 Argument 2: cannot convert from System.Collections.Generic.List<AnimalTracker.Horse> to System.Collections.Generic.List<AnimalTracker.Animal>

Должен ли я "слепок" "Лошадь" Список к типу "Animal" каким-то образом? Или сделать конструктор «AnimalListPage()» менее специфичным для конкретного типа? Как мне это сделать?

Примечание: Я разрабатываю с использованием Xamarin (хотя я не думаю, что это относится к этой проблеме).

+1

вар лошади = новый Список () {... – AndyJ

+2

Просто используйте 'Var лошадей = новый список ()' – Lithium

ответ

2

Просто сделайте свой список List<Animal> как конструктор ожидает:

var horses = new List<Animal>() { 
    new Horse("Silver", 65, 70), 
    new Horse("Tucker", 60, 68) 
}; 

Если вы не контролируете источник значения, и это может быть List<T> любого производного типа, вы хотите выполнить операцию произнесения, чтобы использовать его в качестве List<Animal>:

var horses = someExistingList.Cast<Animal>().ToList(); 
2

Вот некоторые варианты:

простой золь следует использовать List<Animal> вместо List<Horse>. Тогда ваш код будет соответствовать типу, запрашиваемому конструктором.

Подробнее комплекс AnimalListPage общий. Затем вы можете ввести тип Animal, который вы хотите использовать в AnimalListPage. Это будет работать, только если у вас есть один тип Animal, который вы хотите использовать.

Последний вариант - использование интерфейса совместного использования, IAnimal и использовать его в качестве типа списка. Все типы Animal должны реализовать это, но я думаю, вы можете сделать это в своем базовом классе уже. Или используйте интерфейс совместного использования коллекций, например IEnumerable<Animal>.

+0

Пропущенный вариант (любопытное, ваш последний вариант говорит об этом). Если возможно, замените конструктор на «IReadOnlyList », 'IReadOnlyCollection ' или 'IEnumerable ' (все ковариантные интерфейсы). Нет необходимости делать 'IAnimal' –

+0

А, хорошо, вы правы. Обновлено. –

+0

Я отредактировал вопрос, чтобы уточнить, что мне нужно сохранить типы объектов. Имея это в виду, второй вариант «создание« AnimalListPage »более общий, это то, что я хочу. Но как? – IamJohnny45

2

Позвольте мне немного объяснить природу этой ситуации.
Вы не можете неявно преобразовывать коллекцию в коллекцию базового типа, даже если это звучит безопасно и правильно.
Представьте себе следующий случай:

public void CalledMethod(List<Animal> animals) 
{ 
    animals.Add(new Dog()); 
    // error! you've tried to insert a dog into List<Horse> 
} 

public void CallingMethod() 
{ 
    var horses = new List<Horse>() { 
     new Horse("Silver", 65, 70), 
     new Horse("Tucker", 60, 68) 
    }; 

    CalledMethod(horses); 

    string result = horses[2].RideOrDoSomeOtherHorseOnlyThings(); // it would be strange 
} 

Вам необходимо пройти коллекцию Animal либо объявляя List<Animal> вместо List<Horse>, или используя .Cast<Animal>() метод расширения, как уже полностью описана другими отвечающими.

Смежные вопросы