C# 为什么可以';我是否使用System.ValueType作为泛型约束? 为什么我不能使用约束 其中T:System.ValueType 为什么Microsoft会阻止这种类型 从成为一个约束

C# 为什么可以';我是否使用System.ValueType作为泛型约束? 为什么我不能使用约束 其中T:System.ValueType 为什么Microsoft会阻止这种类型 从成为一个约束,c#,generics,C#,Generics,示例: 为什么我不能做以下事情 // Defined in a .Net class public void bar<T>(T a) where T : ValueType {...} // Defined in my class public void foo<T>(T a) where T : ValueType { bar<T>(a); } //在.Net类中定义 公共无效条(TA),其中T:ValueType{…} //在我的课堂上 public

示例:

为什么我不能做以下事情

// Defined in a .Net class
public void bar<T>(T a) where T : ValueType {...}

// Defined in my class
public void foo<T>(T a) where T : ValueType 
{ bar<T>(a); }
//在.Net类中定义
公共无效条(TA),其中T:ValueType{…}
//在我的课堂上
public void foo(ta),其中T:ValueType
{bar(a);}
在ValueType上使用struct有什么区别

// Defined in my class
public void foo<T>(T a) where T : struct 
{ bar<T>(a); }
//在我的类中定义
公共void foo(ta)其中T:struct
{bar(a);}

ValueType不是值类型的基类,它只是装箱时值的容器。由于它是一个容器类,并且不在您想要使用的实际类型的任何层次结构中,因此它不可用作泛型约束。

使用
struct
作为泛型约束在功能上等同于“ValueType”约束。在.NET中,.

使用

where T : struct

  • 后者将允许
    T
    成为
    ValueType
    本身,这是一种引用类型
  • 后者还允许
    T
    为可空值类型
这些差异中的第一个几乎从来都不是你想要的。第二种可能偶尔有用
Nullable
有点奇怪,因为它既不满足
where T:struct
也不满足
where T:class
约束

更有用的是约束

where T : struct, System.Enum

这是C#禁止的,我看不出有什么好的理由。有关这方面的更多信息,请参阅和。

我认为下面的示例涵盖了ValueType所期望的许多用例。T的参数类型?允许空值,并且类型约束将其限制为实现IFormattable的结构,这对于我所能想到的常见值类型是正确的

public void foo<T>(T? a) where T : struct, IFormattable
public void foo(T?a),其中T:struct,IFormattable
请注意,这允许诸如decimal、datetime、timespan之类的类型


我不得不说,我一直在想,我们不能像
那样限制它们,其中t:struct,System.Enum
。有时它会非常有用!实际上,您可以在F#中执行
where T:Enum
where T:ValueType
(使用它的语法
when'T:>Enum
),实际上,它按照Jon的预期工作。对于枚举类型约束,它可以与通用枚举(如
enum
System.enum
)一起使用,并正确地禁止同义值类型(如
byte
int
)。为了回答Jon关于“为什么”的问题,很难将其添加到C#中,请参见Roslyn的讨论:我到了一个地方,实际上我想说ValueType的所有具体实现,包括nullable。(实际约束是其中T:ValueType,New)不完全且不完全。在IL中,您可以清楚地看到任何具有扩展System.ValueType的值类型的声明,这使它有效地成为基类。我认为它的主要作用是作为区分类和值类型的标记,但我不确定。结论(“作为泛型约束不有用”)是正确的,但答案的其余部分不是。ValueType“为值类型提供基类。”(from)和“…它是所有值类型的基类…”(from)结构是
ValueType
,是的,但不是每个值类型都是结构,例如,
ValueType
本身不是结构,也不是可为空的值类型。我认为这个答案不正确,基于公认的答案。
public void foo<T>(T? a) where T : struct, IFormattable