一般情况下都不会改变,除非你用 ref 和 out 关键字

解决方案 »

  1.   

    那要看你的参数是什么类型的,一般数据类型的参数只要不加out ,ref申明是不会被改变的
      

  2.   

    還可用 const加在類型前,這樣如要改變,則會出錯
      

  3.   

    好像加const是一种方法!将其做成属性吧!然后将属性作参数!
      

  4.   

    把参数定义为常量嘛!
    比如:
    const int  a = 10;
    这样就不会被修改了呀!
      

  5.   

    我晕
    难道你们传递的都是value type?
    ref type传递时是不能保证其内部状态不发生改变的。
    C++这种基于value的语言可以使用const,难道在C#里也能在传入的ref type前加上const?
      

  6.   

    你如果要求ref type的内部不发生改变的话,最好clone一下。一般的类都已经给你写好这个clone函数了,如果是你的类,重写一下这个函数,然后clone一个出来。
      

  7.   

    [attributes] [modifiers] const type declarators;
    此处: attributes(可选) 
    可选的声明信息。有关属性和属性类的更多信息,请参阅 C# 属性。 
    modifiers(可选) 
    包括 new 修饰符和四个访问修饰符之一的可选修饰符。 
    type 
    这些类型之一:byte、char、short、int、long、float、double、decimal、bool、string、枚举类型或引用类型。
    没有说引用类型不可以呀!!!!!!!!!!
      

  8.   

    sumtec(Psydian)
    good method, 就是空间有点浪费,如果没有好方法,分就是你的:)
      

  9.   

    snewxf(心疤) 
    看清楚我问的再发话,简直文不对题。
      

  10.   

    我觉得也是clone比较好,好像没有什么更好的办法。
      

  11.   

    支持 不用 out / ref 方法参数
    而clone 不是解。
      

  12.   

    传入的参数默认只是传入其一个copy而已,怎么会改变?
    如果你使用out,ref关键字才会被改变--传入的是地址。
      

  13.   

    要看你是引用传 还是值传递 
    若是引用传 是不会改变的
    若是值类型的话,在传参数的时候,就要加个ref 表明是引用传就可以了
      

  14.   

    Struct的都是传值,
    在C#中Struct是作为原始类型来对待的,
    存在于栈中,
    Class的只能参照,
    存在于堆,由GC管理,
    定义为Const是可以保证不变,
    但是作为定义方式,
    不能保证在调用时不抛出错误。
    Clone相当于原始型的复制,
    需要结构支持IClone接口,
    或由自己来实现IClone接口。至于为什么要用Clone一方面是为了解决语法上的岐义,
    另一方面跟装箱和消箱的实现有关联。
    举个例子清楚些:
    //c#
    string s1 = "aaaaa";
    string s2 = new string(s1); 
    //编译器通知错误,并且建议使用类似Clone的方法。
    [btw:在JAVA中是允许的]想想以下几种情况互转吧:
    ----------------------
    结构到结构
    结构到对像(注意一下是己实例化的和对像工厂的情况)
    对像到结构(注意一下是己实例化的)
    对像到对像
    ----------------------
      

  15.   

    大哥们你们到底懂不懂我问的是什么?
    我简直要faint到死。
      

  16.   

    哎呀呀呀,原来还有这么多人没有搞清楚概念啊??class 相当于 ref struct
    如果参数是一个class,或者说某个变量是一个class,那么实际上这个变量/参数只是一个指针,这个指针指向一个struct。如果你不写ref,或者你的变量定义为const/readonly是没有用的,因为这只是保护了这个指针不被改变,或者作为参数的时候传送的是这个指针的一个拷贝。所以在函数的内部你是不能够改变这个变量,eg:readonly class1 c = new class1();c = new class1();  // 这是不行的,这个指针不能够变
    c.Text = "asdkfs"; // 这样倒是可以的,只要这个Text属性有set,
                       // 或者这个Text字段没有被readonly修饰class1 d = new class1();foo(d);void foo(class1 xxx)
    {
       xxx = new class1();  // 这样是不会修改到外面的d,
                            // 因为这个xxx只是压到堆栈的一个指针的拷贝。
    }foo2(d);void foo2(class1 xxx)
    {
       xxx.Text = "dsafksl" // 但是你却没有办法阻止这个d.Text的改变,因为虽然堆栈
                            // 的是指向某个struct的一个指针的拷贝,但是这个拷贝和
                            // d 一样,指向的是都是同一个struct或者说对象。对xxx.Text
                            // 的修改就是对d.Text的修改。
    }明白了没有?
      

  17.   

    楼主,如果你不希望别人改变你的这个对象,那么你就应该尽量不暴露这个对象才对。或者对那些不应该被修改的属性仅提供get,不提供set。对自己的类应该公开另外一套东西(用internal修饰,但这样其实如果不是情非得已最好不要用)。
    当然,这个的前提是这是你自己写的类。还有一个办法,写一个private/internal的interface,那么只有自己的方法能够通过这个内部的interface访问到。
      

  18.   

    呵, 无语
    千万别以为别人和自己一样无知。好歹我学C++也有几个年头,这点基本概念,我比你清楚。属于同一类作用域中的方法,是可以改变这个类对象的内部状态的。class Base
    {
        public void Fun(Base b)};
      

  19.   

    sorry 发错了class Base
    {
         private int x;
         public void Fun(Base b)
         {
             // b.x = 323;
          }
    }我问的是这里的Base.Fun如何保证不会改变b的内容。因为它可能只需要读取其成员。
      

  20.   

    如果只提供Get,那么在其他情况下需要修改呢?比如不是这个方法。
    用Clone是可以起效果的,但是动静大了点。
      

  21.   

    const是将参数转换成常量了!使用不方便,不推荐!
      

  22.   

    我那个帖子是说给那些给你建议用const或者不用ref的人的,不是写给你的,无需激动。如果是你自己的类里面的东西就应该保证不会出错,没有别的办法。
    像你所说的情况时基本上是没有办法通过限定避免的,只有看你自己的代码质量了。
    你没有说清楚当然不能怪我说得不对啦。当然,如果你能够确定只有某些属性可能会被修改,那么还是有别的办法的,但是就比较复杂了:private bool busy = false;public int MyValue
    {
       get
       {
           return ...;
       }
       set
       {
           if (busy)
               return;
           ... = value;
       }
    }void foo1()            // 这个方法可以命名为SafeFoo2
    {
       myobj.busy = true;  // 这里的myobj可以是this
       foo2(myobj);
       myobj.busy = false;
    }void foo2(myclass obj)
    {
       obj.MyValue = ...;  // 通过foo1可以避免被修改。或者进入前修改busy。
    }当然,这只是一个快速开发方法,对于一个属性还能够胜任,多了就会有各种麻烦。当然,还有好多其他办法。
      

  23.   

    还有就比如说,当你需要禁止某一个函数对某些东西的修改的话,而这样的禁止并不多见,那么你可以在进入这个函数之前进行现场保护,比如说用另一些变量把这些属性都保护起来,然后再进入,退出的时候恢复。其实就是局部Clone。恕我直言,你的问题我是觉得很奇怪,当然,我的意思不是指没有可能出现这样的需求,但是一般来说能够通过一些变换来处理,而不需要“禁止修改”。因为你的这个情况是出现在你自己的类里面的:class Base
    {
         private int x;
         public void Fun(Base b)
         {
             b.x = 323;  // 你的这句话的意思不是期望对这个变量进行修改吗?
                         // 如果你不希望对b.x进行修改,那么就是跟你的原意相矛盾的。
                         // 如果在某种情况下你不希望对他修改,那么就应该在这句话之前
                         // 加上一个判断。如果你这个函数有很多地方对他禁止修改,那么
                         // 你就应该考虑一下,是不是在某种情况下就应该推出这个函数。
                         // 如果还有其他代码在这种情况下是必需的,那么我就觉得那是两个
                         // 不同的功能,应该进行功能分离,不应该写到一个函数里面。
         }
    }
    我不清楚你的目的是什么,你把完整的代码贴出来或许能够帮你。
      

  24.   

    这里写出b.x = 323;只是说明在这里可能改变b的成员,并不是说一定会这样做。有时候我们在自己改变了对象内部成员的时候也不会知道,这种情况比较容易引起逻辑错误。我指的就是这种情况。
    在C++中,由于对象是基于值的,struct 与class在本质上并没有区别,所以可以在参数列里加入const进行声明。这样就能保证参数的内部状态不会发生变化。因为可以传递const ref,所以也没有多的空间开销。
    但是在C#中并不允许在ref上使用const, 因为C#中的const确实是真正的const,没有空间。readonly也只能放在类中的成员上,不能放在传递变量上。你在最后提到的是assert功能吗?那样也可以有效,就是麻烦了点。
    写这个帖子我只是想看看C#中是否有比较方便的方法保证其内部状态不发生改变。
      

  25.   

    不同意sumtec(Psydian) 的说法:
    ---------------
    class 相当于 ref struct
    如果参数是一个class,或者说某个变量是一个class,
    那么实际上这个变量/参数只是一个指针,这个指针指向一个struct。
    ---------------
    在C++中还说的过去,
    那是先定义了对象,
    然后那么马上分配其内存,
    之后调用其构造函数,
    这个内存可能在堆中,
    也可能在栈内,
    也可能在全局数据区内。
    ---
    但C#中却截然不同,定义一对象,
    只是先为其分配一个空间,
    而真正的对象空间还没有分配,
    在使用前当给对象分配空间,
    这个对象空间是分配在堆内的,
    ---
    Struct是标准的分配在栈中,
    Class是指向的堆不是参照到栈中。