---
title: "C# where泛型约束"
author: "Perrin Yong"
author_profile: https://www.pystone.net/profile/
published_by: "Perrin Yong"
canonical: https://www.pystone.net/notes/csharp-generic-where-constraint/
type: note
content_role: unspecified
visibility: public
id_stability: rename-stable
source_path: "10-计算机、信息技术与工程/02-编程语言与运行时/.NET与CSharp/C# where泛型约束.md"
content_hash: 03a4a0f38c90da108e7b7f124d36fe0fa8937d1031600980a4cf35321aa520dd
knowledge_version: 224c990773de.5fa8af6e39fa
site_commit: 224c990773de166d23a886306577dd90379529ce
notes_commit: 5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a
---
# C# where泛型约束

> 创建时间：2020/5/20 17:55

## where泛型类型约束

泛型定义中的 where 子句指定对用作 _泛型类型、方法、委托或本地函数_ 中 **类型参数** 的 **参数类型** 的约束。
约束可指定接口、基类或要求泛型类型为引用、值或非托管类型。

### 约束类型：

#### 接口约束

```xml
public class AGenericClass&lt;T&gt; where T : IComparable&lt;T&gt; { }

```

#### 基类约束

表明用作该泛型类型的类型参数的类型具有指定的类作为基类（或者是该基类）。

> 基类约束一经使用，就必须出现在该类型参数的所有其他约束之前。 某些类型不允许作为基类约束：Object、Array 和 ValueType。 在 C# 7.3 之前，Enum、Delegate 和 MulticastDelegate 也不允许作为基类约束。
>  在 C# 8.0 及更高版本中的可为 null 上下文中，强制执行基类类型的为 null 性。 如果基类不可为 null（例如 Base），则类型参数必须不可为 null。 如果基类可为 null（例如 Base?），则类型参数可以是可为 null 或不可为 null 的引用类型。 当基类不可为 null 时，如果类型参数是可为 null 的引用类型，编译器将发出警告。

```xml
public class UsingEnum&lt;T&gt; where T : System.Enum { }
public class UsingDelegate&lt;T&gt; where T : System.Delegate { }
public class Multicaster&lt;T&gt; where T : System.MulticastDelegate { }

```

#### class和struct约束

> class 约束要求类型是不可为 null 的引用类型。 若要允许可为 null 的引用类型，请使用 class? 约束，该约束允许可为 null 和不可为 null 的引用类型。

```csharp
class MyClass&lt;T, U&gt;
    where T : class
    where U : struct
{ }

```

#### notnull 约束

将类型参数限制为不可为 null 的类型。 该类型可以是值类型，也可以是不可为 null 的引用类型

> 与其他约束不同，如果类型参数违反 notnull 约束，编译器会生成警告而不是错误。 警告仅在 nullable enable 上下文中生成。
>  **重要** ：包含 notnull 约束的泛型声明可以在可为 null 的不明显上下文中使用，但编译器不会强制执行约束。

```csharp
string str1 = &quot;test&quot;;
string str2 = &quot;test&quot;;

```

#### unmanaged 约束

unmanaged 约束将类型参数限制为名为“非托管类型”的类型。 使得在 C# 中编写低级别的互操作代码变得更容易。 此约束支持跨所有非托管类型的可重用例程。 unmanaged 约束不能与 class 或 struct 约束结合使用。 unmanaged 约束强制该类型必须为 struct：

```csharp
string str1 = &quot;test&quot;;
string str2 = &quot;test&quot;;

```

#### 构造函数约束new()

让编译器知道：提供的任何类型参数都必须具有可访问的无参数构造函数。

```csharp
string str1 = &quot;test&quot;;
string str2 = &quot;test&quot;;

```

> 出现在 where 子句的最后。 new() 约束不能与 struct 或 unmanaged 约束结合使用。

## where子句

用在查询表达式中，用于指定将在查询表达式中返回数据源中的哪些元素。 它将一个布尔条件（谓词 ）应用于每个源元素（由范围变量引用），并返回满足指定条件的元素。 一个查询表达式可以包含多个 where 子句，一个子句可以包含多个谓词子表达式。

在下面的示例中，where 子句筛选出除小于五的数字外的所有数字。 如果删除 where 子句，则会返回数据源中的所有数字。 表达式 num < 5 是应用于每个元素的谓词。

```csharp
string str1 = &quot;test&quot;;
string str2 = &quot;test&quot;;

```

一个 where 子句可以包含一个或多个返回布尔值的方法。 在下面的示例中，where 子句使用一种方法来确定范围变量的当前值是偶数还是奇数。

```csharp
string str1 = &quot;test&quot;;
string str2 = &quot;test&quot;;

```
