Можно привести общие параметры C#?

Я написал метод с подписью:

private List<ClientItem> ConvertToClientItems(BaseCollection<object> serverItems)

Я пытаюсь назвать это следующим образом:

ConvertToClientItems(approvedSellers);

где approvedSellers имеет тип BaseCollection<Seller> - с Seller будучи классом, который я не могу контролировать.

Разве это не возможно? Visual Studio выдает ошибку, говоря, что не может привести BaseCollection<seller> в BaseCollection<object>,

2 ответа

Решение

Хорошо, представьте код, который выглядит так:

private List<ClientItem> ConvertToClientItems(BaseCollection<object> serverItems) {
    serverItems.Add(new Buyer());
}

Это должно скомпилировать, так как Buyer является object,

Тем не менее, если вы передаете BaseCollection<Seller>Вы только что попытались добавить покупателя в список продавцов.

Таким образом, утверждение

BaseCollection<Seller>это подтипBaseCollection<object>

только если BaseCollection гарантирует, что универсальный тип T используется только в выходных позициях. Приведенный выше пример добавления будет использовать T в позиции ввода.


Чтобы решить эту проблему, у вас есть следующие варианты:

  • Сделайте BaseCollection "ковариантным", добавив ключевое словоout, которое потребует удаления любого Add методы. Это, однако, может сделать вашу коллекцию бесполезной.
  • Передайте ковариантный интерфейс методу. Если вам нужно только прочитать serverItemsпередать IEnumerable, который уже является ковариантным (и вы упоминаете в комментариях, что BaseCollection уже реализует IEnumerable):

    private List<ClientItem> ConvertToClientItems(IEnumerable<object> serverItems) {
        // You can only read serverItems here, so we are fine.
    }
    
  • сделать сам метод универсальным

    private List<ClientItem> ConvertToClientItems<T>(BaseCollection<T> serverItems) {
        // This also prevents the evil `Add` call, since you'd need to create
        // an object of the correct type T first.
    }
    

В BaseCollection вы должны сделать T ковариантным, используя ключевое слово "out".

Дополнительная информация http://msdn.microsoft.com/en-us/library/dd233059.aspx.

(IEnumerable работает, потому что он ковариантен.)

public interface BaseCollection<out T>
Другие вопросы по тегам