【发布时间】:2023-04-04 07:35:01
【问题描述】:
我阅读了很多可能的答案,但没有找到适合我需要的答案!
我正在尝试声明一个泛型接口,具有不同的非泛型实现类,然后在相同的上下文中使用这些类。
这是我目前所拥有的:
接口
public interface WeirdType { }
public class WeirdType1 : WeirdType { }
public class WeirdType2 : WeirdType { }
public interface IGenericInterface<T>
{
T GiveT();
void TakeItBack(T data);
}
实现
public class NonGenericImplementation1 : IGenericInterface<WeirdType1>
{
public WeirdType1 GiveT() { return new WeirdType1(); }
public void TakeItBack(WeirdType1 data) { Console.WriteLine("Got it back 1"); }
}
public class NonGenericImplementation2 : IGenericInterface<WeirdType2>
{
public WeirdType2 GiveT() { return new WeirdType2(); }
public void TakeItBack(WeirdType2 data) { Console.WriteLine("Got it back 2"); }
}
用法
List<IGenericInterface<WeirdType>> implementations = new List<IGenericInterface<WeirdType>>
{
new NonGenericImplementation1(),
new NonGenericImplementation2()
};
foreach (var impl in implementations)
{
WeirdType x = impl.GiveT();
impl.TakeItBack(x);
}
这让我很震惊
'Argument Type NonGenericImplementation1 is not assignable to IGenericInterface<WeirdType>'
即使一些黑色铸造魔法让我通过编译,它也会在运行时因同样的原因崩溃。
帮助我了解是什么让 C# 打字无法做到这一点和/或建议稍微复杂一点的模式以顺利完成
我可以通过很多不同的方式解决我的实际问题,所以完全替代的解决方案并不是我真正想要的
如果实际答案已经存在,很抱歉浪费时间
【问题讨论】:
-
记录一下:当纯粹使用 getter 时,您可以通过将其声明为
public interface IGenericInterface<out T>来使接口协变。列表实现将按原样被接受,但由于接受的答案中解释的原因,不允许使用 TakeItBack 函数(除非定义为例如void TakeItBack(WeirdType data);) -
我的每个实现本身都包含必要的输入信息!我的意思是,如果在我使用过程中可以使用 (impl.T) 之类的东西而不是 Weirdtype,那么从打字的角度来看,这应该可以工作