在C#中使用Attributes(特性)来控制枚举成员是否应该被序列化或映射
如果标记了[NonSerialized]特性,会防止将该字段序列化。但是,该字段仍然可以用于foreach迭代,因为它仍然是枚举的有效成员。
如果要防止特定枚举成员被foreach迭代,用[NonSerialized]特性是不起作用的。相反,可以创建一个自定义的Attribute继承自System.Attribute,并将其应用到需要隐藏的枚举成员上。在枚举上使用[Flags]特性也将防止它被foreach迭代。
以下是一个示例,防止枚举成员被foreach迭代:
[Flags] public enum SampleEnum { abc, def, [EnumIteratorIgnore] efg } [AttributeUsage(AttributeTargets.Field)] public class EnumIteratorIgnoreAttribute : Attribute { }
foreach (SampleEnum e in Enum.GetValues(typeof(SampleEnum))) { if (e.GetType() .GetField(Enum.GetName(typeof(SampleEnum), e)) .GetCustomAttributes(typeof(EnumIteratorIgnoreAttribute), true) .Length == 0) { yield return e; } }
// 添加 ? 协定后缀 foreach (SampleEnum? e in Enum.GetValues(typeof(SampleEnum))) { if (e?.GetType() // 使用 ?. 运算符 .GetField(e.Value.ToString()) .GetCustomAttributes(typeof(EnumIteratorIgnoreAttribute), true) .Length == 0) { yield return e.Value; } }
在这个示例中,SampleEnum类型被标记为[Flags],这意味着它是一个位标记,不能直接用于foreach迭代。此外,egf枚举成员上定义了一个自定义的EnumIteratorIgnoreAttribute特性,该特性将防止该成员被迭代。
在枚举类型上定义了一个GetEnumValues()方法,该方法遍历枚举类型的所有值,并使用反射来查找每个值的自定义特性。如果枚举值上未发现EnumIteratorIgnoreAttribute特性,则枚举值将被yield返回,否则将被忽略。
因此,在foreach循环中使用GetEnumValues()方法来获取枚举类型的所有值,而忽略在枚举成员上定义了EnumIteratorIgnoreAttribute特性的值。
第三种: Enum.GetValues<SampleEnum>().ToList().ForEach(item => { if (item!.GetType()!.GetField(item.ToString()!)!.GetCustomAttributes(typeof(EnumIteratorIgnoreAttribute), true).Length == 0) { Console.WriteLine(item.ToString()); } });