哪里

where 可以在 C#中实现两个目的:在泛型参数中键入约束,并过滤 LINQ 查询。

在通用类中,让我们考虑一下

public class Cup<T>
{
    // ...
}

T 称为类型参数。类定义可以对可以为 T 提供的实际类型施加约束。

可以应用以下类型的约束:

  • 值类型
  • 参考类型
  • 默认构造函数
  • 继承和实施

值类型

在这种情况下,只能提供 structs(包括’原始’数据类型,如 intboolean 等)

public class Cup<T> where T : struct
{
    // ...
}

参考类型

在这种情况下,只能提供类类型

public class Cup<T> where T : class
{
    // ...
}

混合值/参考类型

有时,需要将类型参数限制为数据库中可用的参数,这些参数通常会映射到值类型和字符串。由于必须满足所有类型限制,因此无法指定 where T : struct or string(这不是有效的语法)。解决方法是将类型参数限制为 IConvertible ,其内置类型为“… Boolean,SByte,Byte,Int16,UInt16,Int32,UInt32,Int64,UInt64,Single,Double,Decimal,DateTime,Char 和 String。 “ 其他对象可能会实现 IConvertible,尽管这在实践中很少见。

public class Cup<T> where T : IConvertible
{
    // ...
}

默认构造函数

仅允许包含默认构造函数的类型。这包括值类型和包含默认(无参数)构造函数的类

public class Cup<T> where T : new
{
    // ...
}

继承和实施

只能提供从某个基类继承或实现某个接口的类型。

public class Cup<T> where T : Beverage
{
    // ...
}

public class Cup<T> where T : IBeer
{
    // ...
}

约束甚至可以引用另一个类型参数:

public class Cup<T, U> where U : T
{
    // ...
}

可以为类型参数指定多个约束:

public class Cup<T> where T : class, new()
{
    // ...
}

前面的示例显示了类定义的泛型约束,但是在提供类型参数的任何地方都可以使用约束:类,结构,接口,方法等

where 也可以是 LINQ 子句。在这种情况下,它类似于 SQL 中的 WHERE

int[] nums = { 5, 2, 1, 3, 9, 8, 6, 7, 2, 0 };

var query =
    from num in nums 
    where num < 5
    select num;

    foreach (var n in query)
    {
        Console.Write(n + " ");
    }
    // prints 2 1 3 2 0