概念问题 类参数传入后改变

.Net技术 码拜 9年前 (2015-05-10) 898次浏览 0个评论
 

有一个类
Class A{a=””,b=””,c=””}

一个方法
static void setvalue(A a)
{
       A newa=new A();
        newa.a=1
        newa.b=2
        newa.c=3
        a=newa;
}

执行 
       A a = new A();
       setvalue(a)
       // 在此处查看参数a,为什么没有变化?
方法内的引用替换没成功?

首先,你根本没有改变传入的a对象的属性,所以传这个参数是多余的。
其次,你是使用 byval 方式传递的对象。你可以试一下:

static void setvalue(ref A a){.......}

不过如果真的需要这样,人家就定义

static A CreateA(){.....}

了。

通常会写成这样

static void Create()
{
       A newa=new A();
         newa.a=1;
         newa.b=2;
         newa.c=3;
         return newa;
}
       A a = CreateA();

其实往往是知识越多越容易乱写。

11分
所谓 byref 传参,就是在调用方法之后将堆栈弹出的对象再赋值给原始的引用变量。也就是这里  void setvalue(ref A a) 这种结果。而所谓的 byval 传参,就是在调用方法之后直接丢弃从堆栈弹出的对象,不进行赋值。不论 A 是值类型还是引用类型,都是一样的机制。

因此在 .net 平台下,byval 通常会比 byref 更快,并且显然也更清晰。除非必要否则不要使用 byref、out。

注意这跟传统的c语言的指针引用是完全不一样的机制。有些人胡乱把c/c++语言的指针机制套用到byref上,虽然有点形似,但是其实是不一样的机制。

29分
C#默认是传值的,这里的值不是object的值,而是ojbect的引用的值。

      A a = new A();
       setvalue(a);     //这里a 执行ObjectA

static void setvalue(A b)   //为了演示,改成b
{
      //这里b这个引用的只和外面的a的值是不同的,但是都指向同一个object  ObjectA. 类似于指针的概念。
       A newa=new A();    //new 了一个新的Object, 叫它OjbectB吧。赋给引用newa.
        newa.a=1
        newa.b=2
        newa.c=3
        b=newa;   //这里把newa引用的值赋给b, b指向ObjectB。但是外面的a引用没有变。
}

如果你要修改引用本身的值,使用ref。 ref的意思是传地址。

static void setvalue(ref A b)  //把实际参数的地址传进来了
{   
       A newa=new A();    
        newa.a=1
        newa.b=2
        newa.c=3
        b=newa;     //修改的是实际参数的值。
}

ref
out
请了解各种关键字
引用 2 楼 sp1234 的回复:

通常会写成这样

static void Create()
{
       A newa=new A();
         newa.a=1;
         newa.b=2;
         newa.c=3;
         return newa;
}
       A a = CreateA();

其实往往是知识越多越容易乱写。

应该是这样:
static A Create(){}
void是没法return newa的

有一个类
    class A
    {
        public int a, b, c;
    }

一个方法
        static void setvalue(A a)
        {
            a.a = 1;
            a.b = 2;
            a.c = 3;
        }

执行
            A a = new A();
            setvalue(a);
            Console.WriteLine(“a={0} b={1} c={2}”, a.a, a.b, a.c);
概念问题 类参数传入后改变

楼主初学,我也初学。我就不喜欢有人非要把问题往深里引,把一个简单的问题弄得异常复杂

用ref,C#基础的东西
引用 4 楼 findcaiyzh 的回复:

C#默认是传值的,这里的值不是object的值,而是ojbect的引用的值。
A a=new A();
static void setvalue(A b)   //为了演示,改成b
{
      //这里b这个引用的只和外面的a的值是不同的,但是都指向同一个object  ObjectA. 类似于指针的概念。
       A newa=new A();    //new 了一个新的Object, 叫它OjbectB吧。赋给引用newa.
        b=newa;   //这里把newa引用的值赋给b, b指向ObjectB。但是外面的a引用没有变。
}

这两句话不太明白,b是A类的实例”a”的一个引用,传入这个引用,相当于传入实例”a”?,但你说”这里b这个引用的只和外面的a的值是不同的“,这想不通,当前认为,传入这个类的某个实例,那就是这个实例本身

引用 1 楼 sp1234 的回复:

首先,你根本没有改变传入的a对象的属性,所以传这个参数是多余的。
其次,你是使用 byval 方式传递的对象。你可以试一下:

static void setvalue(ref A a){.......}

不过如果真的需要这样,人家就定义

static A CreateA(){.....}

了。

在方法中,我将a实例的引用指向 ,直接改成了新new的实例,就是不想一个个属性赋值,但这样为什么不行.

引用 7 楼 xuzuning 的回复:

有一个类
    class A
    {
        public int a, b, c;
    }

一个方法
        static void setvalue(A a)
        {
            a.a = 1;
            a.b = 2;
            a.c = 3;
        }

执行
            A a = new A();
            setvalue(a);
            Console.WriteLine(“a={0} b={1} c={2}”, a.a, a.b, a.c);
概念问题 类参数传入后改变

楼主初学,我也初学。我就不喜欢有人非要把问题往深里引,把一个简单的问题弄得异常复杂

这个我试过呀,是可以的.
在执行方法里新NEW 那个A对象,其数据是来自XML的,并且属性超过18个,总不能给参数对象赋值18回吧.这多不科学

都告诉你加ref了
sp1234
和宝_小孩
就差一点了,我就明白了
引用 9 楼 mirror030 的回复:
Quote: 引用 4 楼 findcaiyzh 的回复:

C#默认是传值的,这里的值不是object的值,而是ojbect的引用的值。
A a=new A();
static void setvalue(A b)   //为了演示,改成b
{
      //这里b这个引用的只和外面的a的值是不同的,但是都指向同一个object  ObjectA. 类似于指针的概念。
       A newa=new A();    //new 了一个新的Object, 叫它OjbectB吧。赋给引用newa.
        b=newa;   //这里把newa引用的值赋给b, b指向ObjectB。但是外面的a引用没有变。
}

这两句话不太明白,b是A类的实例”a”的一个引用,传入这个引用,相当于传入实例”a”?,但你说”这里b这个引用的只和外面的a的值是不同的“,这想不通,当前认为,传入这个类的某个实例,那就是这个实例本身

实例是不会被传入函数的。

lz可能没有接触过指针。
A newa=new A();     newa 分配在堆栈上,其类型可能是int32.是指向object的地址。我所说的值是指这个地址。

static void setvalue(A b)   //传入函数时, b也分配在堆栈上,调用函数时,newa的指向object的地址被传到b上,这是我所说的传值, 外面newa和b,不在同样的位置上,但是值是相同的(指向object的地址。 
….

b=newa;   b这个位置上的值变成指向新的object地址了, 外面的newa却没有改变。

这下应该明白了吧。

我在 #7 已经演示了对象的引用传值

你那样写不行的原因是:
a = newa;
将切断了传入参数 a 对调用时传递的 a 的引用关系(此 a 非彼 a)

对于你的这种写法,需要
在方法中声明 ref(引用) static void setvalue(ref A a)
在调用时声明 ref(引用) setvalue(ref a)

或者同时声明为 out
static void setvalue(out A a)
setvalue(out a)

C#的对象都是传递引用的,根本没有不要使用 ref、out 关键字的必要
而这两个关键字是为不是对象的变量准备的(C#中都是对象,应该是没有用武之地了)

引用 14 楼 findcaiyzh 的回复:

 
实例是不会被传入函数的。

lz可能没有接触过指针。
A newa=new A();     newa 分配在堆栈上,其类型可能是int32.是指向object的地址。我所说的值是指这个地址。

static void setvalue(A b)   //传入函数时, b也分配在堆栈上,调用函数时,newa的指向object的地址被传到b上,这是我所说的传值, 外面newa和b,不在同样的位置上,但是值是相同的(指向object的地址。 
 
b=newa;   b这个位置上的值变成指向新的object地址了, 外面的newa却没有改变。
 
这下应该明白了吧。

是的.明白了.
A类有两个实例,在堆中
A类的引用在栈中,改变引用不会改变堆中的实例,通过引用可能改变堆中实例的属性
并且 实例是不会被传入函数的。

引用 15 楼 xuzuning 的回复:

我在 #7 已经演示了对象的引用传值

你那样写不行的原因是:
a = newa;
将切断了传入参数 a 对调用时传递的 a 的引用关系(此 a 非彼 a)

对于你的这种写法,需要
在方法中声明 ref(引用) static void setvalue(ref A a)
在调用时声明 ref(引用) setvalue(ref a)

或者同时声明为 out
static void setvalue(out A a)
setvalue(out a)

C#的对象都是传递引用的,根本没有不要使用 ref、out 关键字的必要
而这两个关键字是为不是对象的变量准备的(C#中都是对象,应该是没有用武之地了)

感谢  
最不喜欢rel 和 out


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明概念问题 类参数传入后改变
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!