Enum.HasFlag,为什么没有Enum.SetFlag?我必须为我声明的每个标志类型构建一个扩展方法,如下所示:否则标志&=~flag;返回标志;为什么不像有Enum.HasFlag那样有Enum.SetFlag?另外,为什么这不总是有效?publicstaticboolGet(thisEventMessageScopeflags,EventMessageScopeflag){return((flags&flag)!=0);例如,如果我有:varflag=EventMessageScope.Private;并检查它:if(flag.Get(EventMessageScope.Public))其中EventMessageScope.Public确实是EventMessageScope.Private|EventMessageScope.PublicOnly事件消息范围.Private|EventMessageScope.PublicOnly返回true。如果不是,因为Private不是public,只有一半是public。这同样适用于:if(flag.Get(EventMessageScope.None))返回false,除了范围实际上是None(0x0),它应该总是返回true?&运算符将使用a&b,其答案与b&a相同,因此(EventMessaageScope.Private)。Get(EventMessageScope.Private|EventMessageScope.PublicOnly)与write(EventMessageScope.Private|EventMessageScope.PublicOnly)相同。Get(EventMessaageScope.Private)如果您只想知道该值是否与EventMessaageScope.Public相同,则只需使用等于:EventMessageScope.Private==EventMessageScope.Publicfor(EventMessageScope.None).Get(EventMessaageScope.None)您的方法将始终返回false因为None==0并且仅当AND运算的结果不为零时才返回true。0&0==0。为什么没有Enum.SetFlag就像拥有Enum.HasFlag?HasFlag作为按位运算需要更复杂的逻辑并重复相同标志两次myFlagsVariable=((myFlagsVariable&MyFlagsEnum.MyFlag)==MyFlagsEnum.MyFlag);所以MS决定实施它。SetFlag和ClearFlag在C#中简洁flags|=flag;//SetFlagflags&=~flag;//ClearFlag但不幸的是不直观。每当我需要设置(或清除)一个标志时,我都会花几秒钟(或几分钟)思考:该方法的名称是什么?为什么它不显示在智能感知中?或者不,我必须使用按位运算。注意,有些开发者还会问:什么是位运算?是否应该创建SetFlag和ClearFlag扩展-YES出现在智能感知中。开发人员是否应该使用SetFlag和ClearFlag扩展-不,因为它们效率不高。我们在库的类EnumFlagsHelper中创建了扩展,就像在SomeEnumHelperMethodsThatMakeDoingWhatYouWantEasier中一样,但是将函数命名为SetFlag而不是Include和ClearFlag而不是Remove。在SetFlag方法的主体(以及摘要要评论)中我决定添加Debug.Assert(false,"由于性能原因不使用扩展,使用带有解释性注释的按位运算代替nflags|=flag;//SetFlag")并应向ClearFlag添加类似的消息Debug.Assert(false,"由于性能原因不使用扩展,使用带有解释性注释的按位运算代替nflags&=~flag;//ClearFlag")publicstaticclassSomeEnumHelperMethodsThatMakeDoingWhatYouWantEasier{publicstaticTIncludeAll(thisEnumvalue){Typetype=value.GetType();对象结果=值;字符串[]名称=Enum.GetNames(类型);foreach(varnameinnames){((Enum)result).Include(Enum.Parse(type,name));}返回(T)结果;//枚举.Parse(类型,result.ToString());}//////包含枚举类型并返回新值///publicstaticTInclude(thisEnumvalue,Tappend){Typetype=value.GetType();//确定值对象result=value;varparsed=new_Val值ue(附加,类型);if(parsed.Signedislong){result=Convert.ToInt64(value)|(长)已解析。已签名;}elseif(parsed.Unsignedisulong){result=Convert.ToUInt64(value)|(ulong)parsed.Unsigned;}//返回最终值return(T)Enum.Parse(type,result.ToString());}//////检查标志枚举是否设置了特定的标志。//////要检查的标志枚举///要检查的标志///publicstaticboolHasFlag(thisEnumvariable,Enumvalue){if(variable==null)returnfalse;如果(值==null)抛出新的ArgumentNullException(“值”);//不如此函数的.NET4版本//但应该足够好if(!Enum.IsDefined(variable.GetType(),value)){thrownewArgumentException(string.Format("Enumerationtype不匹配。标志的类型为“{0}”,“+”预期为“{1}”。value.GetType(),variable.GetType()));}ulongnum=Convert.ToUInt64(value);返回((Convert.ToUInt64(variable)&num)==n嗯);}//////删除枚举类型并返回新值///publicstaticTRemove(thisEnumvalue,Tremove){Typetype=value.GetType();//确定值对象result=value;varparsed=new_Value(删除,类型);if(parsed.Signedislong){result=Convert.ToInt64(value)&~(long)parsed.Signed;}elseif(parsed.Unsignedisulong){result=Convert.ToUInt64(value)&~(ulong)parsed.Unsigned;}//返回最终值return(T)Enum.Parse(type,result.ToString());}//类来简化//ulong和long之间的缩小值,因为任何一个值都应该//覆盖任何较小的值privatestaticreadonlyType_UInt64=typeof(ulong);公共只读长?签;公共只读ulong?未签名;public_Value(objectvalue,Typetype){//确保它甚至是一个枚举if(!type.IsEnum){thrownewArgumentException("提供的值不是枚举类型!");}//然后检查枚举值Typecompare=Enum.GetUnderlyingType(type);//如果这是一个无符号长整数,那么唯一可以容纳它的//值将是一个ulongif(compare.Equals(_UInt32)||compare.Equals(_UInt64)){Unsigned=Convert.ToUInt64(value);}//否则,long应该涵盖其他任何内容{Signed=Convert.ToInt64(value);我做了一些适合我的事情,这很简单……publicstaticTSetFlag(thisEnumvalue,Tflag,boolset){TypeunderlyingType=Enum.GetUnderlyingType(value.GetType());//注意:AsInt的意思是:数学整数与枚举(不是c#int类型)动态valueAsInt=Convert.ChangeType(value,underlyingType);动态flagAsInt=Convert.ChangeType(flag,underlyingType);如果(设置){valueAsInt|=flagAsInt;}else{valueAsInt&=~flagAsInt;}返回(T)valueAsInt;}使用方法:varfa=FileAttributes.Normal;fa=fa.SetFlag(文件属性。隐藏,真实);回答你的部分问题:Get函数根据二进制逻辑工作正常-它检查任何匹配如果你想匹配整个标志集,请考虑以下内容:return((flags&flag)!=flag);关于“为什么SetFlag不存在”......可能是因为它不是真正需要的。标志是整数。已经有处理这些的约定,它也适用于标志。如果你不想用|写它和&-这就是自定义静态插件的用途-你可以在展示自己时使用自己的功能:)枚举在很久以前就被C语言搞砸了。对于设计人员来说,在C#语言中具有某种类型安全性很重要,当基础类型可以是字节和长整型之间的任何类型时,Enum.SetFlags就没有空间了。顺便说一句,另一个C提出了问题。处理它的正确方法是显式地内联编写这种代码,而不是试图将其推送到扩展方法中。您不想用C#语言编写C宏。这是为任何枚举设置标志的另一种快速而肮脏的方法:publicstaticTSetFlag(thisTflags,Tflag,boolvalue)ToInt32(NumberFormatInfo.CurrentInfo);intflagInt=flag.ToInt32(NumberFormatInfo.CurrentInfo);如果(值){flagsInt|=flagInt;}else{flagsInt&=~flagInt;}返回(T)(对象)flagsInt;}i它被发现的原因是因为枚举是一个值类型,所以你不能传入它并设置它的类型。对于那些认为它很愚蠢的人,我会告诉你:并非所有开发人员都了解位标志以及如何打开或关闭它们(这不直观)。这不是一个愚蠢的想法,只是不可能。以上就是C#学习教程:Enum.HasFlag,为什么没有Enum.SetFlag?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
