我觉得接口(相反?)变化是答案,但无法找到正确的解决方案。
让我们上这几门课:
public abstract class Fruit { }
public class Banana : Fruit { }
public class Apple : Fruit { }
public abstract class Picture { }
public class FruitPicture<T> : Picture, Contravariant<T>, Covariant<T> where T : Fruit
{
T myFruit = null;
public Type GetFruitType() { return typeof(T); }
public void AddFruit(T fruit) { this.myFruit = fruit; }
}
public interface Contravariant<in T> { void AddFruit(T model); }
public interface Covariant<out T> { Type GetFruitType(); }我的情况是:
现在,我试图做一件非常简单的事情,但是以一种通用的方式,这意味着我希望避免在每次发现新的结果时必须更改代码的任何开关/ifs,并且新的FruitPicture可能出现在我想要的集合=>中,从我的集合到正确的FruitPicture类型。我几乎可以更改任何逻辑,但我希望保留泛型的FruitPicture类。
我得到的最接近的是:
foreach(Picture curPicture in myPictures)
{
foreach (Fruit curFruit in myFruits)
{
Covariant<Fruit> fruitType = (Covariant<Fruit>)curPicture;
if (curFruit.GetType() == fruitType.GetFruitType())
{
// what now?
}
}
}谢谢,先生。(开玩笑的;有点)
发布于 2018-10-22 22:02:16
因为您所面临的问题是您想要确保编译时类型的安全性,但在运行时才知道类型,所以可以使用dynamic将决策推送到运行时。我不一定建议这样做,只是说它会起作用。
我将Covariant接口更改为不需要泛型,因为它没有使用类型参数。我将AddFruit重命名为SetFruit,因为它没有添加任何内容,而是替换了。
foreach (var fruit in myFruits) {
foreach (var picture in myPictures) {
if (picture is Covariant cov) {
if (cov.GetFruitType() == fruit.GetType())
((dynamic)picture).SetFruit(Convert.ChangeType((dynamic)fruit, cov.GetFruitType()));
}
}
}需要(dynamic) ChangeType,因为fruit的类型是Fruit,它不是传递给任何SetFruit的有效类型。它必须是动态的,因为ChangeType的静态编译时类型是object,这也不是任何SetFruit的有效类型。
或者,如果您将决定推到FruitPicture中,会怎么样?
public interface Covariant {
void SetCompatibleFruit(Fruit f);
}
public class FruitPicture<T> : Picture, Covariant where T : Fruit {
T myFruit = null;
public void SetCompatibleFruit(Fruit f) {
if (f is T tf)
this.myFruit = tf;
}
}然后,如果可以的话,只需让每个Covariant picture设置fruit:
foreach (var fruit in myFruits) {
foreach (var picture in myPictures) {
if (picture is Covariant cov)
cov.SetCompatibleFruit(fruit);
}
}https://stackoverflow.com/questions/52938167
复制相似问题