C# Where关键字

1. 泛型约束(Generic Constraints)

在泛型类、接口或方法的定义中,where关键字用于指定类型参数的约束。这些约束可以确保类型参数具有某些特定的属性。例如它是一个类、实现了某个接口、是另一个类型的派生类、具有无参构造函数等。

1.1 泛型约束条件表

|-----------------|----------------------------------------------------------|
| 约束名称 | 详情 |
| T:struct | 类型参数必须是值类型,可指定除Nullable以外的任何值类型 |
| T: class | 类型参数必须是引用类型,包括任何类、接口、委托或数组类型 |
| T: new() | 类型参数必须具有无参构造函数(且访问保护等级为public),当与其他约束一同使用时,new()约束必须最后指定 |
| T: <基类名称> | 类型参数必须是指定的基类或派生自指定的基类 |
| T:<接口名称> | 类型参数必须是指定的接口或实现指定的接口,可指定多个接口约束,接口约束也可是泛型 |

1.2 各约束条件使用代码示例

1.2.1 T: struct

public class MyClass<T> where T : struct  
{  
    // 在这里,T 必须是值类型  
    public void MyMethod(T item)  
    {  
        // ...  
    }  
}

1.2.2 T: class

cs 复制代码
public class MyClass<T> where T : class  
{  
    // 在这里,T 必须是引用类型  
    public void MyMethod(T item)  
    {  
        // ...  
    }  
}

1.2.3 T: new()

cs 复制代码
public class MyClass<T> where T : new()  
{  
    //在这里,T 必须具有无参构造函数
    //这个约束允许在泛型类内部创建类型参数类型的新实例
    public T CreateNewInstance()  
    {  
        return new T(); // 调用无参构造函数  
    }  
}

1.2.4 T: <基类名称>

cs 复制代码
public class BaseClass  
{  
    // 基类成员  
    public void BaseMethod()  
    {  
        // ...  
    }  
}  
  
public class DerivedClass1 : BaseClass  
{  
    // DerivedClass1特有的成员  
}  

public class MyClass<T> where T : BaseClass  
{  
    //在这里,T 必须是指定的基类或派生自指定的基类
    // 泛型方法,接受T类型的参数  
    public void MyMethod(T item)  
    {  
        item.BaseMethod(); // 调用基类的方法  
        // 这里可以添加更多逻辑,针对T类型(即BaseClass或其派生类)  
    }  
}  

1.2.5 T: <接口名称>

cs 复制代码
public interface IMyInterface  
{  
    void MyInterfaceMethod();  
}  
  
public class MyClass<T> where T : IMyInterface  
{  
    //在这里,T 必须是指定的接口或实现指定的接口
    public void UseInterfaceMethod(T item)  
    {  
        item.MyInterfaceMethod(); // 调用接口方法  
    }  
}

1.2.6 组合约束

1.2.6.1 class & 接口
cs 复制代码
public interface IMyInterface  
{  
    void MyInterfaceMethod();  
}  
  
public class MyClass<T> where T : class, IMyInterface  
{  
    // 在这里,T 必须是引用类型并实现IMyInterface接口  
    public void UseInterfaceMethod(T item)  
    {  
        item.MyInterfaceMethod(); // 调用接口方法  
    }  
}
1.2.6.1 基类 & 具有无参构造
cs 复制代码
public class MyBaseClass  
{  
    public MyBaseClass() { } // 无参构造函数  
}  
  
public class MyClass<T> where T : MyBaseClass, new()  
{  
    // 在这里,T 必须是MyBaseClass或其派生类,并且有一个无参构造函数  
    public T CreateNewInstance()  
    {  
        return new T(); // 调用无参构造函数  
    }  
}

2. LINQ查询中的条件过滤

LINQ(Language Integrated Query----语言集成查询)提供了一种强大的查询能力,允许你以声明式的方式对集合(如数组、列表等)进行查询和操作。where关键字在LINQ查询中用于指定过滤条件,以筛选出满足特定条件的元素。

示例:查询列表中的元素

假设你有一个Person类,包Name和Age属性

cs 复制代码
public class Person  
{  
    public string Name { get; set; }  
    public int Age { get; set; }  
}  

  

现在有Person对象的列表,如果你想要找出所有年龄大于30岁的人,你可以使用LINQ的where子句来实现:

cs 复制代码
public class MyClass  
{  
    public List<Person> people = new List<Person>  
    {  
        new Person { Name = "张三", Age = 10 },  
        new Person { Name = "李四", Age = 20 },  
        new Person { Name = "王五", Age = 30 },
        new Person { Name = "赵六", Age = 40 },
        new Person { Name = "随便", Age = 50 },
        new Person { Name = "编个名", Age = 60 },
        new Person { Name = "V TheShow", Age = 200 },
    };  
  
    var olderPeople = from p in people  
                      where p.Age > 50
                      select p;  
    public void WriteFilterPeople()
    {
        foreach (var person in olderPeople)  
        {  
            Console.WriteLine(person.Name + " is " + person.Age + " years old.");  
        }  
    }

    //或者使用Lambda表达式
    var olderPeopleLambda = people.Where(p => p.Age > 50);  
    
    public void WriteFilterPeopleLambda()
    {
        foreach (var person in olderPeopleLambda)  
        {  
            Console.WriteLine(person.Name + " is " + person.Age + " years old.");  
        }  
    }
    //上面的两种方式的输出均为
    /*
    编个名 is 60 years old.
    V TheShow is 200 years old.
    */
    
}
相关推荐
向宇it6 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
向宇it8 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
坐井观老天13 小时前
在C#中使用资源保存图像和文本和其他数据并在运行时加载
开发语言·c#
pchmi15 小时前
C# OpenCV机器视觉:模板匹配
opencv·c#·机器视觉
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭17 小时前
C#都可以找哪些工作?
开发语言·c#
boligongzhu18 小时前
Dalsa线阵CCD相机使用开发手册
c#
向宇it1 天前
【从零开始入门unity游戏开发之——C#篇23】C#面向对象继承——`as`类型转化和`is`类型检查、向上转型和向下转型、里氏替换原则(LSP)
java·开发语言·unity·c#·游戏引擎·里氏替换原则
sukalot1 天前
windows C#-命名实参和可选实参(下)
windows·c#
小码编匠1 天前
.NET 下 RabbitMQ 队列、死信队列、延时队列及小应用
后端·c#·.net