区别在于`where t:struct`强制类型参数为值类型(如int、datetime),而`where t:class`强制类型参数为引用类型(如string、自定义类)。前者利用结构体非空且不可继承的特性,后者允许null并支持多态。在实现泛型集合或缓存时,通过指定约束可以消除装箱/拆箱开销或确保对象引用语义。

如何限制T为非可空值类型
使用`where T : struct`不仅要求T是值类型,还隐含排除了Nullable

using System;
public class ValueBox<t> where T : struct
{
private T _value;
public void Set(T value)
{
_value = value;
}
public T Get()
{
// 对于struct,default(T)总是安全的零值
return _value == default(T) ? _value : _value;
}
}
public class Program
{
public static void Main()
{
var box = new ValueBox<int>();
box.Set(42);
Console.WriteLine(box.Get()); // 输出 42
}
}</int></t>
上述代码展示了`ValueBox`类。由于约束了`struct`,编译器保证`T`永远不会是null。如果尝试实例化`ValueBox
如何限制T为引用类型并处理多态
使用`where T : class`允许T成为任何引用类型,包括接口、类、数组和委托。与struct不同,class类型的变量可以是null。这个约束通常用于需要利用多态性(即基类指针指向派生类对象)或需要处理可能为空的对象引用的场景,例如依赖注入或数据加载器。

using System;
public interface IAnimal { string Speak(); }
public class Dog : IAnimal { public string Speak() => "Woof"; }
public class Cat : IAnimal { public string Speak() => "Meow"; }
public class AnimalHandler<t> where T : class, IAnimal
{
public string Process(T animal)
{
if (animal == null) return "No animal";
return animal.Speak();
}
}
public class Program
{
public static void Main()
{
var handler = new AnimalHandler<ianimal>();
Console.WriteLine(handler.Process(new Dog())); // Woof
Console.WriteLine(handler.Process(null)); // No animal
}
}</ianimal></t>
在这个例子中,`AnimalHandler`接受任何实现了`IAnimal`接口的引用类型。约束`class`确保了我们可以安全地检查`animal == null`。如果去掉`class`约束,编译器将不允许对T进行null比较,因为值类型不能为null。同时,`IAnimal`约束利用了class的多态特性,使得同一个处理器能处理Dog和Cat。
当T为class时默认值是什么
当T被约束为class时,`default(T)`的结果永远是null。这与struct的`default(T)`返回零值填充的结构体截然不同。在初始化容器或工厂模式时,必须显式处理null情况,否则可能导致NullReferenceException。











