C# 一般工厂问题、运行时强制转换和co/逆变问题
我作为一名开发人员工作了几年,但似乎我仍然不了解有关泛型的一些高级内容 我准备了一些不言自明的代码:C# 一般工厂问题、运行时强制转换和co/逆变问题,c#,.net,generics,factory,C#,.net,Generics,Factory,我作为一名开发人员工作了几年,但似乎我仍然不了解有关泛型的一些高级内容 我准备了一些不言自明的代码: public enum AnimalType { Cat, Dog} public interface IAnimal { } public class Dog : IAnimal { } public class Cat : IAnimal { } public interface IAnimalHandler<in TAnimal> where TAnimal : IAnima
public enum AnimalType { Cat, Dog}
public interface IAnimal { }
public class Dog : IAnimal { }
public class Cat : IAnimal { }
public interface IAnimalHandler<in TAnimal> where TAnimal : IAnimal { void Handle(TAnimal animal); }
public class CatHandler : IAnimalHandler<Cat>
{
public void Handle(Cat animal) { }
}
public class DogHandler : IAnimalHandler<Dog>
{
public void Handle(Dog animal) { }
}
public class AnimalFactory
{
public IAnimal GetAnimal(AnimalType type) { return type == AnimalType.Cat ? (IAnimal) new Cat() : (IAnimal)new Dog();}
}
public class AnimalHandlerFactory
{
public IAnimalHandler<TAnimal> GetAnimalHandler<TAnimal>(TAnimal animal) where TAnimal : IAnimal
{
switch (animal)
{
case Cat cat:
return new CatHandler() as IAnimalHandler<TAnimal>;
case Dog dog:
return new CatHandler() as IAnimalHandler<TAnimal>;
default:
throw new Exception();
}
}
}
public class FactoryTests
{
[Fact]
public async Task factory_returns_concrete()
{
var myAnimal = new AnimalFactory().GetAnimal(AnimalType.Dog);
var handlerForMyAnimal = new AnimalHandlerFactory().GetAnimalHandler(myAnimal);
Assert.NotNull(handlerForMyAnimal);
}
}
public enum AnimalType{Cat,Dog}
公共接口IAnimal{}
公家犬:IAnimal{}
公共类Cat:IAnimal{}
公共接口IAnimalHandler,其中TAnimal:IAnimal{void Handle(TAnimal animal);}
公共类CatHandler:IAnimalHandler
{
公共空柄(猫科动物){}
}
公共类DogHandler:IAnimalHandler
{
公共空柄(狗类动物){}
}
公营畜牧业
{
public IAnimal GetAnimal(AnimalType){return type==AnimalType.Cat?(IAnimal)new Cat():(IAnimal)new Dog();}
}
公营动物手工厂
{
公共IAnimalHandler GetAnimalHandler(TAnimal动物),其中TAnimal:IAnimal
{
开关(动物)
{
案例类别:
将新的CatHandler()作为IAnimalHandler返回;
个案狗只:
将新的CatHandler()作为IAnimalHandler返回;
违约:
抛出新异常();
}
}
}
公共类工厂测试
{
[事实]
公共异步任务工厂\u返回\u具体()
{
var myAnimal=newanimalfactory().GetAnimal(AnimalType.Dog);
var handlerForMyAnimal=新的AnimalHandlerFactory().GetAnimalHandler(myAnimal);
Assert.NotNull(handlerForMyAnimal);
}
}
现在,你能回答我的疑问吗
1) 为什么我必须在GetAnimalHandler()方法中执行强制转换
2) 测试失败,因为AnimalFactory返回一个抽象对象(声明),并且该类型被用作GetAnimalHandler()方法的泛型类型,因此明显返回null。问题是如何解决这个问题?我遗漏了一些模式吗?你是正确的,你遗漏了一些关于co/逆变的内容,因此在以下位置有了定义:() 协方差 使您能够使用比最初指定的派生类型更多的派生类型 您可以将IEnumerable
定义了您的动物处理程序,这使其具有反变性。根据你的定义,这是合法的
IAnimalHandler<PersianCat> handler = new CatHandler();
如果你想一想,如果你是一个驯养猫的人,你就可以驯养波斯猫。不管你在对付什么样的猫,你都能对付它们
您试图强制执行的案件不合法:
IAnimalHandler<IAnimal> handler = new CatHandler();
IAnimalHandler handler=new CatHandler();
使用我的波斯猫(和专用的处理程序),它看起来是这样的:
IAnimalHandler<Cat> handler = new PersianCatHandler();
IAnimalHandler handler=new PersianCatHandler();
所以,我们有专门的处理程序,只能处理波斯猫,所以我们不能给他只是一个随机的猫,他不知道该怎么办
因此,在法律案例和上文的逆变定义中,更通用的
类型位于赋值的右侧,CatHandler
(或IAnimalHandler
),它被赋值给IAnimalHandler
类型的非通用(或更具体)变量
IAnimalHandler<Cat> handler = new PersianCatHandler();