c# - 转换集合中使用的泛型?
问题描述
假设我想为宠物主人制定饮食计划以保持宠物健康,我有以下课程:
// Pets
public class Pet { ... }
public class Dog : Pet { ... }
public class Cat : Pet { ... }
// Meals and diets
public class Meal<T> : ICollection<T> where T : Pet
{
...
private List<T> allowedPets { get; set; } = new List<T>();
...
}
public class Diet<T> : ICollection<Meal<T>> where T : Pet
{
...
private List<Meal<T>> dietMeals { get; set; } = new List<Meal<T>>();
...
}
虽然我可以有一份可以遵循某种饮食的宠物清单,而不是一份允许吃某些食物的宠物清单,但这只是一个例子。无论哪种方式,我都可以制作一些像这样的任意饮食,以便在某种应用程序中使用它们。
// Dogs and their diets
Dog labrador = new Dog() { ... };
Dog dalmatian = new Dog() { ... };
Meal<Dog> mediumDogBreakfast = new Meal<Dog>(...) { labrador, dalmatian };
Meal<Dog> mediumDogLunch = new Meal<Dog>(...) { labrador, dalmatian };
Meal<Dog> mediumDogDinner = new Meal<Dog>(...) { labrador, dalmatian };
Diet<Dog> mediumDogDiet = new Diet<Dog>()
{
mediumDogBreakfast,
mediumDogLunch,
mediumDogDinner
};
// Cats and their diets
Cat siamese = new Cat() { ... };
Cat sphynx = new Cat() { ... };
Meal<Cat> orientalCatBreakfast = new Meal<Cat>(...) { siamese, sphynx };
Meal<Cat> orientalCatLunch = new Meal<Cat>(...) { siamese, sphynx };
Meal<Cat> orientalCatDinner = new Meal<Cat>(...) { siamese, sphynx };
Diet<Cat> orientalCatDiet = new Diet<Cat>()
{
orientalCatBreakfast,
orientalCatLunch,
orientalCatDinner
};
但是,如果我想将这些饮食放入一个列表中,则会出现转换错误:
// This isn't allowed!
List<Diet<Pet>> = new List<Diet<Pet>>()
{
mediumDogDiet,
orientalCatDiet
};
我的印象是该列表将允许Cat
和Dog
反对,因为Pet
costraint 更笼统,但显然这里出了点问题。如何更改我的Pet
类或集合实现以允许包含狗和猫饮食(或任何其他未来的宠物衍生品)的列表?
解决方案
你需要协方差:
请注意,这意味着您必须创建接口的集合IDiet
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace ConsoleApp8
{
public class Pet { }
public class Dog : Pet { }
public class Cat : Pet { }
// Meals and diets
public interface IMeal<out T> : IReadOnlyCollection<T> where T : Pet
{
}
public interface IDiet<out T> : IReadOnlyCollection<IMeal<T>> where T : Pet
{
}
public class Meal<T> : Collection<T>, IMeal<T> where T : Pet
{
public List<T> AllowedPets { get; set; } = new List<T>();
}
public class Diet<T> : Collection<IMeal<T>>, IDiet<T> where T : Pet
{
public List<Meal<T>> DietMeals { get; set; } = new List<Meal<T>>();
}
class Program
{
static void Main(string[] args)
{
Dog labrador = new Dog() { };
Dog dalmatian = new Dog() { };
Meal<Dog> mediumDogBreakfast = new Meal<Dog>{ labrador, dalmatian };
Meal<Dog> mediumDogLunch = new Meal<Dog>{ labrador, dalmatian };
Meal<Dog> mediumDogDinner = new Meal<Dog>{ labrador, dalmatian };
Diet<Dog> mediumDogDiet = new Diet<Dog>()
{
mediumDogBreakfast,
mediumDogLunch,
mediumDogDinner
};
// Cats and their diets
Cat siamese = new Cat() { };
Cat sphynx = new Cat() { };
Meal<Cat> orientalCatBreakfast = new Meal<Cat>(){ siamese, sphynx };
Meal<Cat> orientalCatLunch = new Meal<Cat>(){ siamese, sphynx };
Meal<Cat> orientalCatDinner = new Meal<Cat>(){ siamese, sphynx };
Diet<Cat> orientalCatDiet = new Diet<Cat>()
{
orientalCatBreakfast,
orientalCatLunch,
orientalCatDinner
};
List<IDiet<Pet>> diets = new List<IDiet<Pet>>
{
mediumDogDiet,
orientalCatDiet
};
}
}
}
推荐阅读
- java - 澄清堆栈是如何通过 Java 中的对象实现的?
- git - 尝试从 Katalon Studio 中的 Git 主分支提取时出现 Git 错误
- visual-studio-code - 用于设置工作目录的 API 或上下文菜单
- java - Windows 7中的JPA Eclipselink查询解析问题
- typescript - VS Code 和 Typescript 观察:文件正在重新编译而不保存
- c# - 提高 TableLayoutPanel 的性能 - C#
- applescript - 将项目移动到特定文件夹
- c# - ITextSharp 合并 PDF 异常
- python-3.x - 如何仅提取文章正文的某些部分?
- node.js - 如何使用 Nodejs 和 Rest API 打开 Excel 文件