C#的OfType()方法是LINQ扩展方法家族中的一员,主要用于从集合中筛选出指定类型的元素,尤其适合处理非泛型集合或者包含多种类型元素的集合场景。它不需要提前知道集合中所有元素的类型,会自动跳过不符合类型的元素,不会抛出异常。

OfType()方法的基本定义
OfType()方法的签名如下,它是IEnumerable接口的扩展方法,定义在System.Linq命名空间下:
public static IEnumerable<TResult> OfType<TResult>(this IEnumerable source);
其中TResult是我们要筛选的目标类型,source是待处理的原始集合。方法会遍历原始集合的每个元素,判断元素是否可以转换为TResult类型,如果可以就加入返回的结果集合中。
基础使用示例
最常见的使用场景是处理ArrayList这类非泛型集合,因为非泛型集合可以存储任意类型的对象,直接遍历时类型不明确,使用OfType()可以快速筛选出我们需要的类型。
示例1:从混合类型集合中筛选字符串
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// 创建包含多种类型的ArrayList
ArrayList mixedList = new ArrayList();
mixedList.Add("hello");
mixedList.Add(123);
mixedList.Add("world");
mixedList.Add(456.7);
mixedList.Add(true);
// 使用OfType筛选字符串类型元素
IEnumerable<string> stringElements = mixedList.OfType<string>();
Console.WriteLine("筛选出的字符串元素:");
foreach (string item in stringElements)
{
Console.WriteLine(item);
}
}
}
上述代码的输出结果是:
筛选出的字符串元素: hello world
可以看到,OfType()自动跳过了整数、浮点数、布尔值这些非字符串类型的元素,只返回了字符串类型的元素。
示例2:筛选自定义类型的元素
除了基础类型,OfType()也支持自定义引用类型的筛选:
using System;
using System.Collections.Generic;
using System.Linq;
// 定义两个自定义类
class Animal { }
class Dog : Animal
{
public string Name { get; set; }
}
class Cat : Animal
{
public int Age { get; set; }
}
class Program
{
static void Main()
{
List<Animal> animals = new List<Animal>
{
new Dog { Name = "小黑" },
new Cat { Age = 2 },
new Dog { Name = "小白" },
new Cat { Age = 3 }
};
// 筛选出Dog类型的元素
IEnumerable<Dog> dogs = animals.OfType<Dog>();
Console.WriteLine("筛选出的Dog实例:");
foreach (Dog dog in dogs)
{
Console.WriteLine($"狗的名字:{dog.Name}");
}
}
}
运行后输出:
筛选出的Dog实例: 狗的名字:小黑 狗的名字:小白
OfType()和Cast()的区别
很多开发者会混淆OfType()和Cast()方法,两者的核心区别在于对不符合类型元素的处理方式:
- OfType():遇到无法转换为目标类型的元素时,直接跳过该元素,不会抛出异常,返回的集合只包含符合类型的元素。
- Cast():遇到无法转换为目标类型的元素时,会直接抛出
InvalidCastException异常。
我们可以通过下面的示例直观看到两者的差异:
using System;
using System.Collections;
using System.Linq;
class Program
{
static void Main()
{
ArrayList list = new ArrayList { "a", 1, "b" };
// 使用OfType筛选字符串,正常执行
var ofTypeResult = list.OfType<string>();
Console.WriteLine("OfType结果:");
foreach (var item in ofTypeResult)
{
Console.WriteLine(item);
}
// 使用Cast转换,会抛出异常
try
{
var castResult = list.Cast<string>();
foreach (var item in castResult)
{
Console.WriteLine(item);
}
}
catch (InvalidCastException ex)
{
Console.WriteLine($"Cast方法抛出异常:{ex.Message}");
}
}
}
运行后输出:
OfType结果: a b Cast方法抛出异常:指定的转换无效。
注意事项
使用OfType()方法时需要注意以下几点:
- 使用OfType()前需要引入
System.Linq命名空间,否则无法调用该方法。 - OfType()返回的是
IEnumerable<TResult>类型,如果需要列表或者数组,可以额外调用ToList()或者ToArray()方法转换。 - 对于值类型,OfType()会进行装箱拆箱操作,如果集合元素数量很多,频繁使用可能会有性能损耗,此时可以考虑其他更高效的筛选方式。
- OfType()筛选的是
is类型匹配的元素,也就是元素类型可以隐式转换为目标类型的都会被筛选出来,比如从Animal集合中筛选Animal类型,会包含所有子类的实例。
适用场景总结
OfType()方法最适合以下场景:
- 处理非泛型集合(如
ArrayList、Hashtable等),需要从中筛选特定类型的元素。 - 集合中元素类型不统一,需要安全筛选指定类型,不希望因为类型不匹配抛出异常。
- 需要从父类集合中筛选出某个子类的所有实例。