在派生对象中使用比父对象定义的更强的类型列表

时间:2015-08-17 16:46:41

标签: c# interface

的信息: IDogShelter和ICatShelter都继承自IAnimalShelter。

接下来,我有Cat和Dog类,它们都实现并扩展了IAnimal。

IAnimalShelter has a List<IAnimal> called Animals.
ICatShelter has a List<Cat> called Animals.
IDogShelter has a List<Dog> called Animals.

问题: ICatShelter没有名为Animals的List,因为IAnimalShelter将它定义为IAnimal列表。 VS说要使用&#34; new&#34;关键词。所以我只是取而代之,并且在IAnimalShelter上没有IAnimal列表。

所以 - 我有一个名为GetAnimalShelters()的方法,它返回IAnimalShelter的List。我希望能够遍历避难所中的每个IAnimal,但不能因为IAnimalShelter没有IAnimal列表。这使我不得不将结果转换为ICatShelter或IDogShelter以便迭代,但我希望能够成功地将IAnimal列表添加到IAnimalShelter中。我怎么能这样做?

例如:

public interface IAnimalShelter
{
    List<IAnimal> Animals { get; set; }
}

public interface ICatShelter
{
    List<Cat> Animals { get; set; }
}

public interface IDogShelter
{
    List<Dog> Animals { get; set; }
}

然后:

List<IAnimalShelter> shelters = GetShelters(search);  //Works
foreach (IAnimalShelter shelter in shelters)
{
    var x = shelter.Animals;  
}

所以上面,我想只访问动物的常见部分,我希望IAnimalShelter拥有一个Animals属性,但是派生的shelter类型要有更强类型的动物列表。

3 个答案:

答案 0 :(得分:1)

您的类型IAnimalShelter承诺其Animals属性将生成一个对象,其Add方法将接受Animal类型的参数。如果ICatShelter派生自IAnimalShelter,则它还必须具有Animals属性,该属性会生成一个对象,其Add方法将接受Animal类型的参数。

要使此模型有效,您应该定义IShelter<out T> where T:Animal,其中包含Animals类型IReadOnlyList<T>的属性,以及TryDonate(Animal it)方法,该方法将请求获取住所一种特殊的动物。 CatShelter : IShelter<Cat>将能够让客户端代码接收可保证所有类型为Cat的对象的可读列表,并且客户可以尝试向其提交任何类型的动物,尽管捐赠类型除Cat之外的其他内容不会添加到列表中。

答案 1 :(得分:0)

这称为泛型。以下定义应该为您提供所需的内容:

public interface IAnimal { }

public class Cat : IAnimal { }

public class Dog : IAnimal { }

public interface IAnimalShelter<T> where T : IAnimal
{
    List<T> Animals { get; set; } 
}

public interface ICatShelter : IAnimalShelter<Cat> { }

public interface IDogShelter : IAnimalShelter<Dog> { }

Animals的{​​{1}}属性为ICatShelter

像这样实现类,编译器很高兴:

List<Cat>

答案 2 :(得分:0)

使用泛型:

public interface IAnimalShelter<T> where T : IAnimal
{
    List<T> Animals { get; set; }
}

public class Cat: IAnimal
{
}

public interface ICatShelter : IAnimalShelter<Cat>
{
}

public class CatShelter: ICatShelter
{
    public List<Cat> Animals { get; set; }
}

没有测试它但是这应该可以解决问题,如果你的ICatShelter没有向IAnimalShelter添加任何东西你甚至可以放弃它并直接从IAnimalShelter派生CatShelter