c#中传递参数除了ref还有out,看资料上介绍他们的主要区别就是,前者必须在调用函数之前初始化,后者必须在函数附值,但我觉得ref可以完成out的全部功能,如果需要的话只需在调用函数的时候初始化为null即可,那c#中加入out有什么特殊的用处吗?那位大哥给介绍一下,小弟不胜感激!

解决方案 »

  1.   

    ref参数在传入前需要初始化
    out参数在传入前不需要初始化out更灵活一些,
      

  2.   

    呵呵,今早我也看这个来着,有篇文章不错,你也看看?
    http://www.chinacs.net/archives/11/2004/08/10/926.html
      

  3.   

    out可以在传入参数的时候可以初始化也可以不初始化,这样比较灵活,但灵活的另一面就是在调用形参为out的方法中必须要给变量赋值,这样但对增加了回调函数的负担,是有些区别的
      

  4.   

    当参数是值类型时,out和ref的区分有两点吧1,明确语义:out在调用函数里必须赋值,语法检查里能确保这个变量确实被函数修改了。
    2,相关性:out在调用函数前的赋值是被忽略的,也就是说与方法调用前的值无关,所以只要声明过就可以了。我自己的迷惑: 当参数是对象类型的时候,不使用ref和out声明,向方法内传递的实际上是对象的引用,同样在方法内部修改对象,这时候ref和out的作用我感到很困惑。召唤达人解答!~
      

  5.   

    out参数就像方法的返回值
    public int Method1(out int r2)
    {
        ...
    }如果你要让Method1方法返回两个值,就只有使用out参数了。
      

  6.   

    在http://www.chinacs.net/archives/11/2004/08/10/926.html里已经说得很清楚了。
      

  7.   

    需要多个返回值得话,out和ref同样达到目的,这不是他们的区别哦!~
      

  8.   

    谢谢各位大哥的指教,不过给我的感觉还是:能用out的地方就能用ref;用out的时候,调用之前不用初始化,但也要定义,而用ref的时候你可以在定义的时候顺便初始化为null,只不过多写“= null”几个字符而已。另外,他们的主要差别好像不在如何实现上,而在于他们各自要追求的目的,比如:用ref一般表示这个参数是in/out的,而用out则表示这个参数是纯 out 的。如果仅仅为了这点目的话,我觉得不太好,因为这个目的可以通过注释或设计书来达到,而且有可能原来定义为out的参数因为某些原因又需要它的传入值,这样的话就要该接口,也不太好。所以我认为out不应该和ref同时出现在c#中,或者能使他们的差别更明显一些。欢迎各位参与讨论。
      

  9.   

    楼主说说为什么不用指针?“也只不过多了...,要注意...而已”放弃了指针,不是为了写程序方便,而是为了写出来的程序更安全、健壮。ref 和 out 也是一样,不是为了你方便或麻烦,而是让你写出来的程序更可靠,更容易维护
      

  10.   

    这位是肉动物同志,能给介绍一下,用out就比用ref写出来的程序更可靠,更容易维护呢??
    兄弟刚接触c#两三个月,只懂皮毛!
      

  11.   

    另外:楼上的楼上……,不知道是几楼的楼上说:
    我自己的迷惑: 当参数是对象类型的时候,不使用ref和out声明,向方法内传递的实际上是对象的引用,同样在方法内部修改对象,这时候ref和out的作用我感到很困惑。
    我的理解是:
    如果在函数体内不对参数开辟新的内存(即重新实例化),那么用不用out或ref是一样的(string类除外,好像string类的操作更像值类型);如果在函数内部要对参数重新实例化,就需要用ref或out了,因为如果不用ref或out的时候,参数实际上传的是对象引用的一个拷贝(就像c语言里船只真参数实际上也是传的指针的拷贝一样),对原来对象的操作就能对对象进行修改,如果要new一个实例的话,只是这个拷贝指向这块内存,而原来的对象引用还是指向原来的内存空间。况且参数的生存期只在函数体内,出了函数对他分配的内存也应该被回收。
      

  12.   

    楼上的说的有道理。举个例子:
    public class ClsTest
    {
      public int intX;  public ClsTest()
      {
        intX = 0;
      }
    }static void Func( ClsTest argClsTest )
    {
      argClsTest = new ClsTest();
      argClsTest.intX = 7456;
    }static void Main(string[] args)
    {
      ClsTest m_cls = new ClsTest();
      
      Func( m_cls );  Console.WriteLine( m_cls.intX );
    }
    返回的结果是0;如果Func使用了ref关键字,那么结果就变成了7456。至于“用out就比用ref写出来的程序更可靠”,这个说法不对吧,out和ref都是表示参数使用引用传递的关键字,它们配合使用使参数用途更明确:ref,掉用方法前必须被初始化;out,调用方法里必须被初始化。举例就不用了吧,你很聪明的。
      

  13.   

    赫赫,楼上和我想的一样,“使参数用途更明确”这才是真正的目的,我的意思是微软没必要这样做。因为本来都是很简单的东西,却使得大家不得不花很多时间去弄懂他们之间细微的差别。反正我是查了不少资料的,到最后他们之间还是那么一点差别,所以我感觉被骗了,就来论坛里和大家讨论一下,发发牢骚,赫赫。本来我发过另外一篇帖子,好像语言有点过激,第二天就被删了,5~~~~~!所以这次改的缓和了一点,谢谢大家的观点。既然微软的牛人在c#中加入out,应该有更好的道理吧,但我们要抱着怀疑的态度看待问题,以不至于太教条,尽信书则不如无书嘛。这帖子暂时还不结,欢迎高手接续给出自己的想法。
      

  14.   

    ref是引用参数,引用参数不创建新的存储位置,引用参数的值总与基础变量相同out修饰的参数是输出参数,与那个对函数成员调用中当作“自变量”的变量在同一个位置,
    参数的值总与基础变量相同两个还是有区别的,上面说的赋值是一部分
    在有:
    在函数成员内部,引用参数被做为初始已赋值,输出参数视为初始未赋值(2)引用参数在函数调用前必须明确赋值,输出参数在函数返回前必须已明确赋值
      

  15.   

    ①ref要求参数必须被初始化,out没有这个要求。
    ②ref参数可以被修改,也可以不被修改,但是out必须被赋值或者修改。
    ③ref参数值可以在任何时候被调用参数使用,而out参数值只能在被赋值后才可以被使用。
      

  16.   

    为了C#语言的编译检查,在值类型上这一点更能体现.
    如:
    int i;int j = i;//Error,变量i没有被初始化。实际上就是为了这个。======神奇的分隔线=======void Test( out int i )
    {
      int j = i;//Error,变量i没有被初始化。
    }又如:void Test ( ref int i )
    {
      int j = i;//正确
    }//=========神奇的分隔线=========int i;
    Test ( i );//Error,变量i没有被初始化。
      

  17.   

    biduan(笔端) 兄弟说:ref是引用参数,引用参数不创建新的存储位置,引用参数的值总与基础变量相同out修饰的参数是输出参数,与那个对函数成员调用中当作“自变量”的变量在同一个位置,
    参数的值总与基础变量相同
    什么基础变量,自变量的,自变量是数学中的概念吧,编程当中我还没听说过呢,麻烦老兄给解释一下基础变量和自变量好吗?你这两句话兄弟是一点没看懂,我开始怀疑自己的智商了,赫赫。
      

  18.   

    Ivony()老兄举的例子不错,
    biduan(笔端)同志说:在函数成员内部,引用参数被做为初始已赋值,输出参数视为初始未赋值
    你俩是一个意思,一个给出理论,一个给出实践,不错,谢了
      

  19.   

    我认为Ivony的例子里最后的Test( i )没有被声明过吧;
    另外有一点:out/ref和传值参数之间可以看作函数重载的区别,但是仅仅out和ref的区别对IL是一样的,无法区分重载!
      

  20.   

    wagada()是正确的,
    不行你可以写两个函数,查看IL代码,里面是一样的,我以前看过,好象都会编译成out(不是很确认)了
      

  21.   

    http://iheshi.cnblogs.com/articles/132852.html
      

  22.   

    我认为Ivony的例子里最后的Test( i )没有被声明过吧;
    另外有一点:out/ref和传值参数之间可以看作函数重载的区别,但是仅仅out和ref的区别对IL是一样的,无法区分重载!
    第二条神奇的分隔线下面的代码与上面的是在同一个类里面的,只不过下面的代码写在了某个函数里,我懒得虚构那个函数而已.....神奇的分隔线就是说省掉了一大堆东西.