T的通用约束同时为引用类型和值类型?

17

我对泛型约束的工作原理存在疑问,感觉自己缺少了一些重要的知识点。我在评论中提出了我的问题,希望能得到解答。

//1st example:

class C <T, U>
    where T : class
    where U : struct, T
{
}
//Above code compiles well, 
//On first sight it looks like U might be reference type and value type
//at the same time. The only reason I can think of, is that T may be an 
//interface which struct can implement, Am I correct?

//2nd example

class CC<T, U>
    where T : class, new ()
    where U : struct, T
{
}

//I added also a reguirement for parameterless constructor
//and, much to my surprise, it still compiles what is
//a bit inexplicable for me.
//What 'U' would meet the requirement to be 
//value type, reference type and have a contructor at the same time?
1个回答

17

这没问题。让我们看一下类型参数的约束的定义:

  • T : class - 类型参数 T 必须是引用类型,包括任何类、接口、委托或数组类型。
  • U : struct - 类型参数 U 必须是值类型。
  • U : T - 类型参数 U 必须是类 T 或从类 T 派生的。

所以你需要做的就是找到一个从引用类型派生的值类型。一开始可能听起来不可能,但如果你再仔细思考一下,你会想起所有结构体都从类object派生,所以这对你的两个示例都适用:

new C<object, int>();

然而,如果你交换structclass,它就不会编译:
// Error - Type parameter 'T' has the 'struct' constraint so 'T'
//         cannot be used as a constraint for 'U'
class C<T, U>
    where T : struct
    where U : class, T
{
}

1
是的?你为T指定了它,这将匹配对象构造函数。没问题。 - Lasse V. Karlsen
是的,你说得对,我读错了。@Mark Byers你说所有结构体都派生自object。所以如果我有一个类CS<T> where T : class{},像这样的代码CS<DateTime> obj = new CS<DateTime>();就行不通了,尽管DateTime可以转换为对象。 - nan
@Andrzej Nosal:是的,因为约束T:class并不意味着T可转换为对象。它意味着T必须是引用类型。DateTime不是引用类型。 - Mark Byers
1
C<Enum, someEnumeratedType>同样有效 ;) - Hans Passant
@Hans Passant:+1 好观点 - 或许令人惊讶的是,类型ValueType是一种引用类型,因此 C<ValueType, int> 也可以工作。 :) - Mark Byers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接