Почему я не могу передать Список <Клиент> в качестве параметра к методу, который принимает Список <объект>?

Это не может точно попасть в 'grep' категорию, но я не мог продвинуться в Windows без утилиты, названной AgentRansack. Это - находящееся в gui, "находят в файлах" утилиту с поддержкой regex. Это очень просто, чтобы щелкнуть правой кнопкой по папке, совершить нападки, "роются.." и найдите файлы, содержащие, что Вы ищете. Чрезвычайно быстро также.

12
задан Edward Tanguay 2 December 2009 в 16:59
поделиться

8 ответов

.NET не имеет ковариации и противоречивости (пока).

То, что B является производным от A, не означает, что List является производным от List < A> . Это не так. Это два совершенно разных типа.

.NET 4.0 будет иметь ограниченную ковариацию и контр-дисперсию.

14
ответ дан 2 December 2019 в 03:54
поделиться

Это проблема ковариантности, и это не так просто, как кажется на первый взгляд. В C # 4 для этого есть некоторая поддержка.

Чтобы понять проблемы, представьте в вашем случае, что это приведение действительно сработает. Теперь у вас есть List , который, например, также имеет метод Add . Однако аргументом для фактического Add должен быть Customer , так что это явно нарушает реализацию;
8
ответ дан 2 December 2019 в 03:54
поделиться

C # (в настоящее время) не поддерживает дисперсию для универсальных типов.

Однако, если вы используете C # 3.0, вы можете сделать это:

FillSmartGrid( customers.Cast<object>() );
7
ответ дан 2 December 2019 в 03:54
поделиться

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

Вот мой стандартный ответ о том, как обойти проблему:

List<A> listOfA = new List<C>().ConvertAll(x => (A)x);

или:

List<A> listOfA = new List<C>().Cast<A>().ToList();

Также здесь действительно хорошее объяснение от самого Эрика Липперта, один из главных архитекторов в команде C #.

6
ответ дан 2 December 2019 в 03:54
поделиться

Это было до тошноты освещено во многих других ответах. Краткий ответ таков:

Считайте, что у меня есть эти переменные:

List<Customer> customers = new List<Customer>(); //ok, seems fair
List<object> objects = new List<object>(); // again, everything's fine

Вот где он перестает компилироваться:

objects = customers; // sounds OK, since a Customer is an object, right?

objects.Add("foo"); 

Теперь это имеет смысл?

C # 4.0 представит ограниченные возможности делать то, что вы попытки, хотя возможность выполнить точно , как вы описываете (назначить List для List , не будет разрешено для того же рассуждения я изложил выше). См. блог Эрика Липперта для получения дополнительной информации и исправления некоторой дезинформации, которая распространяется в сети.

Чтобы ответить на ваш комментарий выше, нет причин, по которым вы можете '

2
ответ дан 2 December 2019 в 03:54
поделиться

Вместо передачи List, который не работает по указанным выше причинам, не могли бы вы просто передать просто ссылку на объект, а затем получить тип списка, вроде как ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1 {

    class Customer {
        public int id;
        public string name;
    }

    class Monkey {

        public void AcceptsObject(object list) {

            if (list is List<Customer>) {
                List<Customer> customerlist = list as List<Customer>;
                foreach (Customer c in customerlist) {
                    Console.WriteLine(c.name);
                }
            }
        }
    }

    class Program {
        static void Main(string[] args) {

            Monkey monkey = new Monkey();
            List<Customer> customers = new List<Customer> { new Customer() { id = 1, name = "Fred" } };
            monkey.AcceptsObject(customers);
            Console.ReadLine();
        }
    }
}
1
ответ дан 2 December 2019 в 03:54
поделиться

Почему параметр не может иметь тип IList?

public void FillSmartGrid (IList items)

0
ответ дан 2 December 2019 в 03:54
поделиться

Я согласен с ответом Уинстона Смита.

Я просто хотел указать в качестве альтернативы (хотя, возможно, это не лучший способ справиться с ситуацией), что while List не является производным от List , Customer [] действительно является производным от Object [].

Следовательно, можно сделать следующее:

    {
        List<Customer> customers = new List<Customer>();
        // ...
        FillSmartGrid(customers.ToArray());
        // ...
    }

    public void FillSmartGrid(object[] items)
    {
    }

Конечно, Обратной стороной является то, что вы создаете объект массива только для того, чтобы передать его этой функции.

0
ответ дан 2 December 2019 в 03:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: