我已经阅读了所有关于协变、逆变和不变的内容,但我仍然不知道如何设计我的代码
I've read all about Covariance, Contravariance and Invariance, but I still don't get how to design my code
我已经搜索并 read/studied 在发布这篇文章之前,我尽可能多地搜索了似乎合理的内容。我发现了类似的问题,但大多数帖子实际上更多地涉及将 "List of a derived types" 传递给需要 "List of a base type" 的函数调用。我可以欣赏动物的例子,感觉学习后我有更好的把握。
话虽如此,我仍然无法弄清楚如何解决我的特定用例。我需要在集合中聚合 "GenericClass of TestInterface(s)" 的实例。我已经 copied/pasted 尽最大努力完成任务,这似乎是完成任务的最佳方式。
namespace Covariance
{
class Program
{
protected static ISet<GenericClass<TestInterface>> set = new HashSet<GenericClass<TestInterface>>();
static void Main(string[] args)
{
set.Add(new GenericClass<A>());
set.Add(new GenericClass<B>());
}
}
class GenericClass<TemplateClass> where TemplateClass : TestInterface
{
TemplateClass goo;
}
public interface TestInterface
{
void test();
}
public class A : TestInterface
{
public void test()
{
}
}
class B : A
{
}
}
以上代码因以下编译错误而失败:
error CS1503: Argument 1: cannot convert from 'Covariance.GenericClass' to 'Covariance.GenericClass'
error CS1503: Argument 1: cannot convert from 'Covariance.GenericClass' to 'Covariance.GenericClass'
任何 help/guidance 或相关链接将不胜感激。如果这是一个重复的问题,我再次表示歉意。谢谢!
您只能在泛型接口上声明变体修饰符(in、out),而不能在类型上声明。因此,解决此问题的一种方法是为您的 GenericClass
声明接口,如下所示:
interface IGenericClass<out TemplateClass> where TemplateClass : TestInterface {
TemplateClass goo { get; }
}
class GenericClass<TemplateClass> : IGenericClass<TemplateClass> where TemplateClass : TestInterface
{
public TemplateClass goo { get; }
}
然后
class Program {
protected static ISet<IGenericClass<TestInterface>> set = new HashSet<IGenericClass<TestInterface>>();
static void Main(string[] args) {
set.Add(new GenericClass<A>());
set.Add(new GenericClass<B>());
}
}
我已经搜索并 read/studied 在发布这篇文章之前,我尽可能多地搜索了似乎合理的内容。我发现了类似的问题,但大多数帖子实际上更多地涉及将 "List of a derived types" 传递给需要 "List of a base type" 的函数调用。我可以欣赏动物的例子,感觉学习后我有更好的把握。
话虽如此,我仍然无法弄清楚如何解决我的特定用例。我需要在集合中聚合 "GenericClass of TestInterface(s)" 的实例。我已经 copied/pasted 尽最大努力完成任务,这似乎是完成任务的最佳方式。
namespace Covariance
{
class Program
{
protected static ISet<GenericClass<TestInterface>> set = new HashSet<GenericClass<TestInterface>>();
static void Main(string[] args)
{
set.Add(new GenericClass<A>());
set.Add(new GenericClass<B>());
}
}
class GenericClass<TemplateClass> where TemplateClass : TestInterface
{
TemplateClass goo;
}
public interface TestInterface
{
void test();
}
public class A : TestInterface
{
public void test()
{
}
}
class B : A
{
}
}
以上代码因以下编译错误而失败:
error CS1503: Argument 1: cannot convert from 'Covariance.GenericClass' to 'Covariance.GenericClass'
error CS1503: Argument 1: cannot convert from 'Covariance.GenericClass' to 'Covariance.GenericClass'
任何 help/guidance 或相关链接将不胜感激。如果这是一个重复的问题,我再次表示歉意。谢谢!
您只能在泛型接口上声明变体修饰符(in、out),而不能在类型上声明。因此,解决此问题的一种方法是为您的 GenericClass
声明接口,如下所示:
interface IGenericClass<out TemplateClass> where TemplateClass : TestInterface {
TemplateClass goo { get; }
}
class GenericClass<TemplateClass> : IGenericClass<TemplateClass> where TemplateClass : TestInterface
{
public TemplateClass goo { get; }
}
然后
class Program {
protected static ISet<IGenericClass<TestInterface>> set = new HashSet<IGenericClass<TestInterface>>();
static void Main(string[] args) {
set.Add(new GenericClass<A>());
set.Add(new GenericClass<B>());
}
}