我无法明确表达问题所以我将从一个例子开始:
public class BirdCollector
{
protected Dictionary<string, Bird> nameToBird_;
public BirdCollector(Dictionary<string, Bird> nameToBird)
{
nameToBird_ = nameToBird;
}
}
public class ExoticBirdCollector
{
public ExoticBirdCollector(Dictionary<string, Bird> nameToBird)
: base(nameToBird)
{ }
public ExoticBird GetExoticBird(string name)
{
Bird bird;
if(nameToBird_.TryGetValue(name, out bird))
{
return (ExoticBird)bird;
}
else
{
// handle error
return null;
}
}
}
我传入ExoticBirdCollector
的词典包含所有ExoticBird
,其中Bird
延伸,但我不得不每次都在GetExoticBird()
重播它们。
是否可以在构造函数中投射一次,这样每次我从nameToBird_获得一只鸟时它都是ExoticBird
?编译器没有任何方式知道我在地图中传递了所有ExoticBirds
,所以有没有办法强制执行此操作而不是声明单独的字典,例如Dictionary<string, ExoticBird> nameToExoticBird_
?
我现在正在考虑做的事情(这似乎不正确)是将BirdCollector
中的nameToBird_设为私有而不是受保护,并将其隐藏在ExoticBirdCollector
字符串和ExoticBird
的字典中。 / p>
我原来的问题得到了解答,但我有一个相关的跟进。如果我要求Dictionary<string, ExoticBird>
被传递到一个在构造函数中接受Dictionary<string, Bird>
的新类,我怎么能实现呢?我怀疑无法进行向下投射,因为对象在容器内。我可以创建一个新的Dictionary<string, Bird>
并循环遍历Dictionary<string, ExoticBird>
来填充它然后传递它,但这看起来像是一个黑客。
答案 0 :(得分:4)
使您的基类具有通用性并移动GetBird
方法
public class BirdCollector<T> where T : Bird
{
readonly Dictionary<string, T> nameToBird_;
public BirdCollector(Dictionary<string, T> nameToBird)
{
nameToBird_ = nameToBird;
}
public T GetBird(string name)
{
T bird;
if (nameToBird_.TryGetValue(name, out bird))
{
return bird;
}
// handle error
return null;
}
}
然后你可以像这样声明它的派生类
public class ExoticBirdCollector : BirdCollector<ExoticBird>
{
public ExoticBirdCollector(Dictionary<string, ExoticBird> nameToBird)
: base(nameToBird)
{
}
}
答案 1 :(得分:1)
您可以使用泛型和类型约束:
public class Bird
{ }
public class ExoticBird : Bird
{ }
public class BirdCollector<T> where T : Bird
{
protected Dictionary<string, T> nameToBird_;
public BirdCollector(Dictionary<string, T> nameToBird)
{
nameToBird_ = nameToBird;
}
}
public class ExoticBirdCollector : BirdCollector<ExoticBird>
{
public ExoticBirdCollector(Dictionary<string, ExoticBird> nameToBird)
: base(nameToBird)
{ }
public ExoticBird GetExoticBird(string name)
{
ExoticBird bird;
if (nameToBird_.TryGetValue(name, out bird))
{
return bird;
}
else
{
// handle error
return null;
}
}
}