我遇到了类似于以下代码的运行时转换错误。首先,我有一个访问者模式的接口设置:C#运行时将约束泛型类型转换为约束类型
public interface IAnimalVisitor<out T>
{
T Visit(Dog a);
T Visit(Cat a);
}
public interface IAnimal
{
string Name { get; }
T Accept<T>(IAnimalVisitor<T> v);
}
public abstract class AnimalBase : IAnimal
{
public string Name { get; }
protected AnimalBase(string name)
{
Name = name;
}
public abstract T Accept<T>(IAnimalVisitor<T> v);
}
public class Dog : AnimalBase
{
public Dog(string name) : base(name) { }
public override T Accept<T>(IAnimalVisitor<T> v)
{
return v.Visit(this);
}
}
public class Cat : AnimalBase
{
public Cat(string name) : base(name) { }
public override T Accept<T>(IAnimalVisitor<T> v)
{
return v.Visit(this);
}
}
然后一个类实现访问者模式(隐藏的嵌套类):
public class AnimalSpeaker
{
private class SpeakerVisitor : IAnimalVisitor<string>
{
public string Visit(Dog a)
{
return "Woof";
}
public string Visit(Cat a)
{
return "Meow";
}
}
private readonly SpeakerVisitor _SpeakerVisitor = new SpeakerVisitor();
public string Speak(IAnimal a)
{
return a.Accept(_SpeakerVisitor);
}
}
最后我有一个泛型类受限于消耗类型IAnimals,它通过它的包封类传递一个实例给访问者的:
public abstract class AnimalSignTextBuilderBase<TAnimal>
where TAnimal : IAnimal
{
private readonly AnimalSpeaker _AnimalSpeaker = new AnimalSpeaker();
public string BuildSignText(TAnimal a)
{
var spokenText = _AnimalSpeaker.Speak(a);
return $"{a.Name} says {spokenText}.";
}
}
public class DogSignTextBuilder : AnimalSignTextBuilderBase<Dog> { }
public class CatSignTextBuilder : AnimalSignTextBuilderBase<Cat> { }
此代码编译完全正常,但在运行时(它是从一个被称为n ASP.net请求)当我打电话
new DogSignTextBuilder().BuildSignText(new Dog("Fido"))
我得到一个无效的转换异常。这是由致电_AnimalSpeaker.Speak(a)
造成的。
我不知道为什么会抛出。更重要的是,我可以在Visual Studio中调试代码,并在即时窗口中输入a is IAnimal
,从而产生true
。我还可以在即时窗口中输入_AnimalSpeaker.Speak(a)
和它导致以下错误:
error CS1503: Argument 1: cannot convert from 'TAnimal' to 'IAnimal'
我还可以利用这个例子和dotnetfiddle张贴,并把它做工精细,所以在这一点上,我在关于发生了什么事情的想法完全丧失。
编辑:我还发现,由于刚刚在即时窗口调用a.Name
失败:
error CS1061: 'TAnimal' does not contain a definition for 'Name' and no extension method 'Name' accepting a first argument of type 'TAnimal' could be found (are you missing a using directive or an assembly reference?)
我检查了我的引用和他们都在那里。到目前为止,似乎通用约束在运行时被忽略。我也可以输入(a as IAnimal).Name
,正确返回Fido
。
你完全可以减少到最小的例子吗?我不会认为我们需要所有的代码才能显示问题。 –
虽然你声称它是一个*例外*并不能很好地适应编译器错误“错误CS1503”...... –
我发现了一些更多的信息,表明其余的代码是一个红鲱鱼。我想尽可能地完整,因为这对我来说毫无意义。 –