ArLi2003(阿利 路过.NET) 
>>>就是或运算,微软的常数通常是以位1 其它为0为标准,所以| 时可以+ 一样的效果
大部分枚举常量确实如此。不过"|"与"+"概念完全不一样。不能误导啊!就算严格满足你说的条件,也不是一样的效果,如:1|1=1,而1+1=2;再如:4|4=4;而4+4=8;他们都是1位为1,就象微软的枚举常量一样,但"位或"与相加不一样啊!
 再"Or"或"||"一般是表示逻辑"或",同"|"也不是一回事。

解决方案 »

  1.   

    同意 
    skykevin(天下) 
    和 
    jjcccc()
      

  2.   

    晕jjccc 我没有说 | 和 + 是相等的你去查下微软的SDK,它的常数标准是这样排的(二进制):000001 000010 000100 001000 010000 100000 类推,所以在VC 上很多人包括我习惯用|
      

  3.   

    ArLi2003(阿利 路过.NET) :
    4:二进制为:00000100,但00000100|00000100 与 00000100+00000100一样吗?
      

  4.   

    呵呵,可能你不是很理解| 在微软界的参数重加法,比如楼主的例子:this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
    | System.Windows.Forms.AnchorStyles.Left) 
    | System.Windows.Forms.AnchorStyles.Right)));其实就是 this.dateTimePicker1.Anchor = ((((System.Windows.Forms.AnchorStyles) 1|2)|4)|8);System.Windows.Forms.AnchorStyles. 的 top 是1,2进制为 0001
    的Bottom是2,2进制为 0010
    left是4,2进制为 0100
    right是8,2进制为 1000所以它们的| 和+ 是一样的,至于说的 00100 和 00100 这种二个相同的常数相和是不存在的,因为我上面已经说了,微软的常数都是以单个位为1其它都为0
      

  5.   

    比如:this.textBox1.Anchor = (System.Windows.Forms.AnchorStyles)(1|2|4|8);
    this.textBox1.Anchor = (System.Windows.Forms.AnchorStyles)(1+2+4+8);是一样的,因为微软的常数是不可能有任何一个BIT 是与同应用域的其它常数相同的(某个bit 不可能同时为1)这就是为什么2之后是4之后又是8 的原因,这是它的一个规则
      

  6.   

    呵呵,继续研究:
    在微软的标准常数上是相等的==》
    this.textBox1.Anchor = (System.Windows.Forms.AnchorStyles)(1|1|1|1);this.textBox1.Anchor = (System.Windows.Forms.AnchorStyles)(1+1+1=1);
    一样吗?不信作个Form试试。
    当然一般情况下绝对不会这么用,但用来作例子足以说明在C,C++,C#语言里,"|"和"+"绝对不一样。只不过在某些情况下(如你说微软标准常数,那是因为你每个参数都不一样,也就是说没有两个参数在同一位上都视"1")碰巧运算结果一样罢了。就比方数学上2+2=4;8-4=4,总不能说"+"和"-"是一样的效果罢?
      总之,"|"和"+"是任何时候都绝对不是一回事。要不你比较两个运算符反汇编后的汇编码看看,就知道真正的区别在哪了!
      

  7.   

    对不起,打错了一个字符,上面
    this.textBox1.Anchor = (System.Windows.Forms.AnchorStyles)(1+1+1=1);应该是
    this.textBox1.Anchor = (System.Windows.Forms.AnchorStyles)(1+1+1+1);
      

  8.   

    jjcccc完全正确,而ArLi2003大概是笔误,大家就不必再纠缠了。我个人认为jjcccc的解释非常到位,讲出了问题的本质,尤其对于这样一个非常简单的问题,绝对不能从表面现象看结果。有时候就是这样,越是简单的问题就越有嚼头。:)
      

  9.   

    或运算和加运算谁不知道是有差别。。你的意思是要我去学一下和运算是怎么回事罗,呵呵晕,我不是说了,微软的常数没有存在1+1 这种算法,所有的常数都不可能有任何一位是相同的,只可能是1|2|4 这样的加法,不可能有1|2|3 这样的加法,你找找微软同域有哪个常数是有2 又有3 的。。因为3的2进制是 00000011 这样的话和 1 的二进制 00000001 存在和运算上的冲突,因为二个数的第8 个bit 都是1 存在相同是不允许的,所以微软的常数加法用|和+是相同的。比如上面的,为什么微软定义四个常数为 1/2/4/8 而不是 1/2/3/4?因为top 的常数值是1,二进制为 0001,Bottom是2,二进制为 0010
    则 left 必须是4 以上而不能是3或1或2(因为会有bit 相同是会与和运算冲突),right也必须是8 而不能是5或7 这样的,不知你明白没有从事高级编程的朋友是会不理解,慢慢就会接触到了
      

  10.   

    不过最后一次:如下
    this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Top) 
    | System.Windows.Forms.AnchorStyles.Left) 
    | System.Windows.Forms.AnchorStyles.Left)));
    大概没有人(包括c#编译器)规定不允许这么做吧!
      

  11.   

    再深入一些吧:假设 System.Windows.Forms.AnchorStyles 是一个8bit 的数:top 的常数值是1,二进制为 00000001,Bottom是2,二进制为 00000010由于后二个bit 都已经被占用,所以第三个常数只能是 1-6 bit可用,所以它选择了第六个bit 置1,所以 left 必须是4 以上而不能再是1-3 之间任何数,之后的 right 也因为后三个bit 被占用,只能使用 1-5 bit 所以它只能是8 以上而不能是 1-7 之间任何数所以就有了不可能有相同常数相加的情况,这是微软常数的规则,不懂的要学会理解它,应该不难因为只可能有:0001 | 0010 而不可能有 0001| 0011 这种情况,更不可能有 0001|0001 这样的 。。(-_-!)
      

  12.   

    非也,this.textBox1.Multiline = true;this.textBox1.Anchor = (System.Windows.Forms.AnchorStyles)(System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Left);this.textBox1.Anchor = (System.Windows.Forms.AnchorStyles)(1|2|4|8);这二种都是正宗的VC 风格,你自己在C# 试一下行不行
      

  13.   

    上文有二个常数写错了,应为:this.textBox1.Anchor = (System.Windows.Forms.AnchorStyles)(System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right);
      

  14.   

    to ArLi2003(阿利 路过.NET):
    问题越辩越名,不好意思,犯一次戒:
    >>>更不可能有 0001|0001 这样的 。。
      那只是在正确的情况下,你不会这么写,但不是说不允许这么写。比如无意中写错了代码总是有。
      诚心对ArLi2003说一句。你的理解确实有一点小湾没有转过来。若这样,估计写程序的时候,可能容易出些许逻辑上的错误,就是编译和允许都没有问题,但就是得不到自己要的结果。而一旦程序这种错误,还特别难查,所以训练一下严密性没有坏处。
      不妥之处,请谅解!
      

  15.   

    因为你的2个 top 和2个left 违背了不能有二个有bit 位相同的常数进行和的原则而编译器是不会对这种正当的运算进行检查,所以可以编译,但值属于非法
      

  16.   

    要知道象你所举的那个例 top|top 换成 top+top 也是一样的非法值,所以只可能是在常数定义上出错,而不可能在| 和+ 上出错,理解了这些道理,在以后我们自己写常数时也会顾虑到的
      

  17.   

    top|top=top,合法且没有问题;但top+top=2*top,合法,但可能有问题。
      

  18.   

    晕,你还真是牛。。你换成+ 的话得到的是 2*top 一样非法值(因为在常数运算|就是+,所以如果|不允许有相同bit 的数相和也就相当于不能有二个相同的常数相加),你自己试,这就是微软常数的精妙之处,它的精处在于:top+top =4; 这是正当的值,也就变成了left 所以就被误会了
    而如果你是习惯于 top|top = 2 它就还是原意top,就不会出错了这就是为什么用| 而不用+ 的原因
      

  19.   

    to ArLi2003:大哥,你是高人你可以很明白怎么做才对,可是既然是技术论坛,最好是给大家一种最正确的用法,以避免有意或无意的错误。对于这个问题,最准确的说法应该是“在特殊情况下”位或运算等同于加法运算,然而两者从概念上绝非可以互相替代的。也就是说,只要是对位标志进行组合运算就一定要用或运算符(|)而绝不可以用加法运算符(+)。我说“绝不可以”是有充分理由的,试问如果你有一个函数,其功能是对某一个可能已经有值的位标志变量组合一个新的标志位,你会怎么写呢?就算所有的常数都已经定义为独位的标志,可是你不能保证传入的标志在该位上一定为0啊!如下:void EnsureFlag(ref int flags, int newFlag)
    {
      flags |= newFlag;
    }对比:void EnsureFlag(ref int flags, int newFlag)
    {
      flags += newFlag;
    }两者在运行时绝对是有天壤之别!我想如果你在程序中写+=的话,甭说高级程序员,恐怕连最初级的程序员都不会让你做的。另外,关于你所说的“微软的常数规则”其实只是一种简单的现象而已,而且你对这个现象的观察可能还不够仔细,事实上微软也定义了一些非独位的常数,这些常数用于表示一些常见的组合,如XXX_DEFAULT,他可能等于XXX_FLAG1|XXX_FLAG2。这时候你写XXX_DEFAULT|XXX_FLAG1肯定是没错的,然而你写XXX_DEFAULT+XXX_FLAG1肯定就有问题了(编译没问题不等于程序没问题)!总之,|与+绝对是两码事,决不能因为在某些特定的情况下两者可以有相同的答案就认为他们可以相互替换,这绝对是一个严重的问题!技术上的事情容不得半点马虎的!如有得罪还请原谅——为了大多数人对真理的正确理解吧!谢谢:)
      

  20.   

    同理,用于排除标志位也只能用and not,绝不可以用-。开关标志是用异或运算(exclusive-OR)^,没有简单的数字运算可以代替。OVER!
      

  21.   

    JGTM2000(铁马小子) ,你不简单!看来我是老朽了,有些问题总以为对方应该明白的,就蜻蜓点水似的说一下,反而这样越说越说不清楚!还是你不含含糊糊!这点得向你学习(真心话!)。因为的确,技术上的事情容不得半点马虎的!。我很早以前做过导弹、卫星发射时的跟踪引导程序。从而有机会接触到或听到国外或前人一些因为程序上一点点小Bug(比这帖子讨论的问题性质还轻!),就导致巨大惨痛的后果的实例。
      

  22.   

    还可以说的更彻底一些:位操作对CPU(Intel)来说,一般是test指令,而+就是add指令。
    再可以说更更彻底,那就要说道数字逻辑电路了,哈哈。
      

  23.   

    使用“|”来处理的枚举在定义时一定要加上属性[Flags],如
    //权限字枚举类型
    [Flags]
    public enum RightWordEnum
    {
    NdaSetting = 0X00000001,
    Measure = 0X00000002,
    SaveData = 0X00000004,
    ViewData = 0X00000008,
    ModifyData = 0X00000010,
    BackupData = 0X00000040,
    Template = 0X00000100,
    User = 0X00001000,
    SurveyPoint = 0X00010000,
    }
      

  24.   

    补充,[Flags]属性不是必加的,然而对于标志位枚举类型则加上它有若干好处。以上面朋友给出的枚举定义为例,设RightWordEnum rightWord = RightWordEnum.SaveData | RightWordEnum.User,你可以看看rightWord.ToString()在[Flags]有和没有两种情况下的差别(对于懒得动手的朋友,可以告诉你在有Flags属性的时候ToString会输出文本表示的枚举值,如“SaveData, User”),同理你也可以写rightWord = Enum.Parse("ViewData, Template")这样的语句把字符串解析为枚举值。甚至在定义了复合位标志的时候这一技巧仍然管用(如你可以定义RightWordEnum.AllRights = 0x000000FF,当所有8个位都被设置后,rightWord.ToString将直接输出AllRights)。这是一个非常实用的.NET特性噢!供您参考,不要拍我!:)