我正在尝试将泛型类型设置XmlAttribute
为XmlElement
允许的类型,但是当我同时设置它们时,我在编译过程中遇到错误:
类类型约束“System.Xml.XmlElement”必须位于任何其他约束之前
代码示例:
interface TestClass<T, T2> : IEnumerable where T2: XmlAttribute, XmlElement
{
...
}
为什么它不允许我设置这样的约束?
您使用的约束不代表允许类型的列表。这意味着“任何插入的东西都T2
必须继承自 。”
这样编译器就可以确保插入的任何东西都T2
提供了特定的公共接口——属性和方法——,即那些从指定类型继承的接口。如果您可以在那里列出多个替代方案,那么哪个接口会被认为是理所当然的?根据要插入的内容,T2
可以具有由 提供的所有方法和属性,也可以具有由 提供的XmlAttribute
所有方法和属性XmlElement
,但没有一个是肯定的。
当您列出用逗号分隔的多个约束时,您告诉 C#T
必须满足所有* 这些约束,而不是一个或另一个。你不能做一个约束说它T
必须是两个类之一。通过约束类型参数,您可以将允许的操作和方法调用的数量增加到约束类型和您列为类型约束的所有接口所支持的数量。这就是首先拥有基于类型类和基于接口的约束的目的——让您调用超出System.Object
类支持的操作。
因此,您永远不会将两个类放在约束列表中(当然,您可以根据需要放置一个类和任意数量的接口)。即使这两个类是相关的,将派生最多的类放入约束中也等同于将它们都放入其中。
请记住,and 之间的逗号XmlAttribute
表示XmlElement
and , not or。XmlAttribute
andXmlElement
是类,并且由于 C# 没有多重继承,因此任何泛型参数都不可能满足约束。
你不能这样做的原因是这两种类型有不同的成员。想想在一个方法上使用这个,体内会发生什么?在不知道传入哪种类型的情况下如何编写方法?自动完成将如何应对这种约束?
您最好的选择是选择通用基类 - System.Xml.XmlNode
,或者创建两个单独的接口,一个带有. XmlAttribute
,另一个带有XmlElement
.
例如:
public interface ICommonInterface<T> : IEnumerable
{
//common things that rely only on the first type go here
}
public interface IAttributeInterface<T, T2> : ICommonInterface<T>
where T2 : XmlAttribute
{
}
public interface IElementInterface<T, T2> : ICommonInterface<T>
where T2 : XmlElement
{
}
如果接口的主要目标是在大多数情况下同时使用这两种类型,那么您应该使用XmlNode
约束或包装类 ala Adapter/Facade 模式。