使用Find()方法根据枚举值查找集合中的实例
问题原因与解决方案
嘿,我一眼就看出问题出在哪了——这是枚举装箱导致的引用比较陷阱!
先看你的代码:Foo类里的EnumValue是基类Enum类型,而你往集合里加的是FooEnum.First(值类型枚举)。当你把值类型的枚举赋值给Enum类型的属性时,.NET会自动把它装箱成一个Enum对象。
假设你查找的代码是类似这样的:
var foundFoo = fooCollection.FirstOrDefault(f => f.EnumValue == FooEnum.First);
这里的核心问题是:f.EnumValue是已经装箱的Enum对象,而FooEnum.First会被重新装箱成另一个全新的Enum对象。对于Enum这种引用类型,==默认比较的是对象的引用地址,而不是枚举的实际值。两个不同的装箱对象引用肯定不一样,所以条件永远不成立,自然返回null。
解决方法有两种,选哪种看你的需求:
1. 改用具体枚举类型(推荐)
如果你的Foo类只需要存储FooEnum类型的枚举,直接把属性类型改成FooEnum,彻底避开装箱问题:
public class Foo { public FooEnum EnumValue { get; set; } }
这时候再用f.EnumValue == FooEnum.First查找,就是值类型的直接比较,完全没问题。
2. 保留Enum基类时的正确比较方式
如果必须用Enum基类(比如要支持多种枚举类型),那比较的时候要换方式:
- 用
Equals方法:它会专门处理枚举的值比较,不管装箱情况:var foundFoo = fooCollection.FirstOrDefault(f => f.EnumValue.Equals(FooEnum.First)); - 先转换为具体枚举类型(要注意类型安全):
或者强制转换(如果确定类型匹配的话):var foundFoo = fooCollection.FirstOrDefault(f => f.EnumValue is FooEnum fooEnum && fooEnum == FooEnum.First);var foundFoo = fooCollection.FirstOrDefault(f => (FooEnum)f.EnumValue == FooEnum.First);
这样就能正确找到集合里的对象啦!
内容的提问来源于stack exchange,提问作者Oystein
相关产品推荐
相关产品推荐

