C# 通用接口和协变性——与无效卡斯特例外作斗争
这可能是一个经典的协方差/反方差问题,它看起来应该有效,但我可能错过了一个技巧。 我试图从工厂方法返回派生度较低的类型,但我发现无法将更专业化的具体实例转换为派生度较低的基类型C# 通用接口和协变性——与无效卡斯特例外作斗争,c#,generics,covariance,C#,Generics,Covariance,这可能是一个经典的协方差/反方差问题,它看起来应该有效,但我可能错过了一个技巧。 我试图从工厂方法返回派生度较低的类型,但我发现无法将更专业化的具体实例转换为派生度较低的基类型 public class AnimalSettings { ... } public class CatSettings : AnimalSettings { ... } public interface IAnimalService<TSettings> { ... } public abstrac
public class AnimalSettings { ... }
public class CatSettings : AnimalSettings { ... }
public interface IAnimalService<TSettings> { ... }
public abstract AnimalService<TSettings> : IAnimalService<TSettings> where TSettings : AnimalSettings { ... }
public class CatService : AnimalService<CatSettings> { ... }
这可以很好地编译,但在运行时,我的代码在尝试转换返回IAnimalService new CatService时失败;,带着一个无效的例外
我应该如何将派生度较高的类型转换为派生度较低的类型,以便调用者可以使用该接口基类型调用功能
将强制转换更改为IAnimalservice new CatService确实有效,但其目的是让调用者接收IAnimalservice,以便它可以处理任何种类的动物。换句话说,调用者不应使用任何更专门的类型。我应该在某个地方将输入或输出指定为通用定义的一部分吗?通过给出一个完整的示例,这将更容易提供帮助- 这就是答案。正如Sweeper已经提到的,您需要在接口处添加out参数以使其工作
using System;
public class Program
{
public static void Main()
{
var catService = new CatService(new CatSettings());
var genericService = (IAnimalService<AnimalSettings>)catService;
genericService.DoAnimalBehavior();
}
}
public abstract class AnimalSettings
{
public abstract void DoAnimalBehavior();
}
public class CatSettings : AnimalSettings
{
public override void DoAnimalBehavior()
{
Console.WriteLine("Meeoh");
}
}
public interface IAnimalService<out TSettings>
{
void DoAnimalBehavior();
}
public abstract class AnimalService<TSettings> : IAnimalService<TSettings> where TSettings : AnimalSettings
{
private readonly TSettings _settings;
public AnimalService(TSettings settings)
{
_settings = settings;
}
public void DoAnimalBehavior()
{
_settings.DoAnimalBehavior();
}
}
public class CatService : AnimalService<CatSettings>
{
private readonly CatSettings _catSettings;
public CatService(CatSettings catSettings)
: base(catSettings)
{
_catSettings = catSettings;
}
}
它应该是IAnimalService,但取决于您在IAnimalService中使用的方法,强制转换成功可能没有意义,在这种情况下,当您尝试添加时,将出现编译器错误。
var service = MyServiceFactory.GetAnimalService(AnimalType.Cat);
service.DoAnimalBehavior();
using System;
public class Program
{
public static void Main()
{
var catService = new CatService(new CatSettings());
var genericService = (IAnimalService<AnimalSettings>)catService;
genericService.DoAnimalBehavior();
}
}
public abstract class AnimalSettings
{
public abstract void DoAnimalBehavior();
}
public class CatSettings : AnimalSettings
{
public override void DoAnimalBehavior()
{
Console.WriteLine("Meeoh");
}
}
public interface IAnimalService<out TSettings>
{
void DoAnimalBehavior();
}
public abstract class AnimalService<TSettings> : IAnimalService<TSettings> where TSettings : AnimalSettings
{
private readonly TSettings _settings;
public AnimalService(TSettings settings)
{
_settings = settings;
}
public void DoAnimalBehavior()
{
_settings.DoAnimalBehavior();
}
}
public class CatService : AnimalService<CatSettings>
{
private readonly CatSettings _catSettings;
public CatService(CatSettings catSettings)
: base(catSettings)
{
_catSettings = catSettings;
}
}