出了一个面试题,如下:
请写出下面代码的运行结果,并解释为什么?
using System;
public class Test1
{
public static void Main()
{
int num = 0;
Person p = new Person("Li");
A1(p, num);
Console.WriteLine("{0},{1}", p.name, num);
}
static void A1(Person p, int num)
{
p = new Person("Wang");
num = 1;
}
}
public class Person
{
public string name;
public Person(string name)
{
this.name = name;
}
}
10个人面试,10个人都回答错误,难道这题很难?
这是我在实际开发中遇到过的问题,所以列入了面试题中
你也来回答看看
并说说有没有必要面试这种题目
请写出下面代码的运行结果,并解释为什么?
using System;
public class Test1
{
public static void Main()
{
int num = 0;
Person p = new Person("Li");
A1(p, num);
Console.WriteLine("{0},{1}", p.name, num);
}
static void A1(Person p, int num)
{
p = new Person("Wang");
num = 1;
}
}
public class Person
{
public string name;
public Person(string name)
{
this.name = name;
}
}
10个人面试,10个人都回答错误,难道这题很难?
这是我在实际开发中遇到过的问题,所以列入了面试题中
你也来回答看看
并说说有没有必要面试这种题目
输出的是这两个..不可能10个人都回答错误.
两个p都引用Li那个对象,后来,第二个p引用了Wang,这对第一个p不会影响
两个num存储在不同位置,更不会相互影响了
所以,Li 0
Li,0关键是分析这个函数:A1(Person p, int num)
P是以引用形式传进来的,num是以值形式传进来的,所以在Al()中对num的修改不会返回到调用Al()的函数中;
Al()函数中的p是引用,所以对P的修改会影响p的值,但引用也是复制后传到Al()函数中的,所以对P的副本重新赋值不会影响到p,但对p副本的属性赋值会影响到p,这大概就是引用;
Person p = new Person("Li");
A1(p, num);
这句话打印的变量是局部的,更上面A1(p,num)没有关系。
Console.WriteLine("{0},{1}", p.name, num);
using System;
public class Test1
{
public static void Main()
{
int num = 0;
Person p = new Person("Li");
A1(p, num);
Console.WriteLine("{0},{1}", p.name, num);
}
static void A1(Person p, int num)
{
p.name = "Wang";
num = 1;
}
}
public class Person
{
public string name;
public Person(string name)
{
this.name = name;
}
}
就不同了
string:String
public class Test1
{
public static void Main()
{
int num = 0;
Person p = new Person("Li");
A1(p, num);
Console.WriteLine("{0},{1}", p.name, num);
}
static void A1(Person p, int num)
{
p.name = "Wang";
num = 1;
}
}
public class Person
{
public string name;
public Person(string name)
{
this.name = name;
}
}
如果改成这样,输出Wang, 0
此时,A1中引用的是p的地址,所以当p值改变后,Main中的p也变。
{
p = new Person("Wang"); //这里的p指向的是一个新开辟的内存块。呼~其实就这么简单。
因为是复制的引用,所以没有影响到原来的p (没有采用p.Name方式修改)。所以结果还是第一个对象li。
对象方法中的对象类型按引用传递,值对象按值传递.
所以int按值传递,方法中的修改不影响变量本身的值.
Person p是对象,按引用传递,方法中的操作会影响对象.就这样.
public static void Main()
{
int num = 0;
Person p = new Person("Li");//称其为p1...
A1(p, num);//p1引用的副本,不是p1了...
Console.WriteLine("{0},{1}", p.name, num);
}
static void A1(Person p, int num)//p1引用的副本...
{
p = new Person("Wang");//称其为p2...与p1不相干,与p1引用的副本也不相干...
num = 1;
}
知其然不知其所以然...同意39楼的意见...
{
p = new Person("Wang");我是以内存块的角度考虑的。这两个new出来的内存块是独立的。其实这个就够了。
就不是原来的实例的引用了,构造器会重新分配内存空间存放新实例
基础知识啊
在这个示例里是一个简单类,如果是关键性的东东,比如换另一个数据库连接……
按你的说法,C#就不应该提供ref out这样的关键字了?
经过A1(P,num)调用后,原p赋值"Li"将更改为"Wang",同时num也会更改为1。
其实这不是答题人的问题 是阁下自己都不知道为什么namhyuk其实是理解了意思 但是说法可能欠妥当或者说准确
如果引用类型得成员被重新赋值了,那么实参的成员也会改变,因为他们操作的是同一个地址,如果形参被new了,那么形参和实参没有了任何关系了
值类型形参和实参本来就没有关系,当然以上情况强制引用除外
首先我声明一下我不是什么大虾
其次在CSDN里对事不对人 希望LZ不要介意这里,p是一个引用,num是一个值。对p赋值的时候,实际上把一个对象付给了这个引用。但问题是,p本身是值,包含了实参的值,也就是A1(p, num);这个调用中的p的内容(指向Person对象的引用)。如果在函数A1中修改了p的内容,只是修改了参数p的指向,而不是外面调用时的那个实参p。
至于void A1(ref Person p, ref int num){} 在这种声明下,当调用A1时,编译器会把实参p的地址作为参数传递进去,此时修改参数,改的是实参p的地址内的东西
其实可以这样理解咯:
对一个引用对象,引用的指针(p1)放在栈,指针所指向的是对象内容放在堆.
调用一个函数,
这时,会在栈上把p1复制一份(值复制),形成p2,同样,p2和p1一样也是指向堆中同一个地址的.
即在
static void A1(Person p, int num)
{
p = new Person("Wang");
num = 1;
}
中,参数Person p,即为p2,
p2 = new Person("Wang");
使p2指针指向了一个新申请的堆中的位置.
结果,p2的值变了.p1的值没有变.
所以,主函数:
Console.WriteLine("{0},{1}", p.name, num);
时,p.name,即为p1所指向的内容.所以是
li
不知我理解得对不对?
在楼主的示例中,p为引用类型,在未使用 ref 参数的情况下传递给方法A1。在此情况下,将向方法传递指向p的引用的一个副本。但是在A1方法中使用 new 运算符来分配新的内存部分,将使A1中的p引用新的Person,因此,这之后的任何更改都不会影响原始Person p(它是在 Main 内创建的)。实际上,本示例中创建了两个Person对象,一个在 Main 内,一个在 A1 方法内
using System;
public class Test1
{
public static void Main()
{
int num = 0;
Person p = new Person("Li");
A1(ref p, num);
Console.WriteLine("{0},{1}", p.name, num);
Console.Read();
}
static void A1(ref Person p, int num)
{
p = new Person("Wang");
num = 1;
}
}
public class Person
{
public string name;
public Person(string name)
{
this.name = name;
}
}
A1(Person p)
{
p = new Person("Wang");
}
和
A1()
{
Person x = new Person("Wang");
}是一样的。这个意义上,传这个引用变量的人有些弱智。
fun(ival);
编译器会把ival复制到栈上,作为参数。这样,i实际上是在栈上,你修改i,只修改了栈上的内容,等到退出函数,栈回滚,i的内容也就消失了
void fun(int* i)
fun(&ival)
此时的参数类型是指针,编译器会把ival的地址作为参数的值压到栈里,这样,参数i实际上就是指向ival的指针,修改这个指针指向的内容可以修改对象(*i=...),但如果只修改i,就是修改了指针的内容,对ival的值没有影响这是从C++上面来理解的 不知道是不是我误会了阁下的说法了