C#中何时使用值类型/引用类型约束有用?

6
我正在寻找一些简单的示例,以展示何时使用值类型/引用类型约束是有用的。
... where T : struct  // when is this useful?
... where T : class   // and what about this?

我记得以前看到过一些非常好的例子,但我现在找不到它们了。
3个回答

11

如果 TT:class,则允许您在 T 上使用 as 运算符。

如果 TT:struct,则禁止您将其与 null 进行比较。

请注意,如果省略了 T:class,即使 T 是值类型,您也可以将其与 null 进行比较。

[注:在发布之前我需要多次编辑才能达到正确的效果。我希望现在已经正确了。]


1

我发现它的主要用处在于对象的封送和内存固定。

例如,我经常处理无法自动转换或作为字节流发送到网络的内部结构,因此我编写了这个帮助程序:

public static T PinAndCast<T>(this Array o) where T : struct
{
    var handle = System.Runtime.InteropServices.GCHandle.Alloc(o, GCHandleType.Pinned);
    T result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    handle.Free();
    return result;
}

我认为创建新实例取决于“T:new()”约束,而不是类/结构约束?此外,我对C#中的Marshalling和内存固定并不是很熟悉,您能否提供一个代码示例? - Oak
这完全取决于具体的细节。在我的情况下,我需要将现有的一组字节转换为结构体。但是,创建新实例确实取决于new()约束。我已经编辑了我的回答以反映这一点。 - Jeff Hubbard

-1
"

T : class" 会强制指定的泛型类型为类,而不是值。例如,我们可以创建一个 ObjectList 类,该类要求指定的泛型类型为类,而不是值:

class ObjectList<T> where T : class {
  ...
}

class SomeObject { ... }

ObjectList<int> invalidList = new ObjectList<int>();  //compiler error

ObjectList<SomeObject> someObjectList = new ObjectList<SomeObject>(); //this works

这将对您的泛型类型T施加一个不可强制执行的不变量。"T:struct"也可以起到同样的作用。请注意,您还可以使用此结构来强制执行类型T不仅是类,而且还匹配接口。我从中提取代码示例也有

class MyList<T> where T : class, IEntity { ... }

这将强制T成为一个类,同时也是IEntity。


谢谢,但我已经了解了泛型约束的语义 - 我想要的是结构体/类约束有用的例子。 - Oak

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