代码说明 - 面向对象的编程

时间:2014-10-07 10:46:49

标签: c#

请看这段代码:

 public class User
 {
     public string username = String.Empty;
 }

 static void Main(string[] args)
 {
     int counter = 10;
     User john = new User();
     User paul = new User();

     Execute(counter, john, ref paul);

     Debug.WriteLine(counter);
     Debug.WriteLine(john == null ? "null" : john.username);
     Debug.WriteLine(paul == null ? "null" : paul.username);
 }

 public static void Execute(int ctr, User John, ref User Paul)
 {
     ctr++;
     John.username = "John";
     John = null;
     Paul.username = "Paul";
     Paul = null;
 }

注意"执行"的第三个参数是通过引用传递的。 该程序将输出:

10 
John
null

所以,我理解以下内容:

  • " 10"价值和
  • 第三行
  • null

但是为什么对象John仍然有用户名" John"即使它得到了NULL? (对象被破坏)

4 个答案:

答案 0 :(得分:3)

  

John获得了他的用户名然后被销毁了,为什么他仍然存在于静态Main?

因为User john = new User()做了两件事:

  1. 创建类型为User
  2. 的实例
  3. john
  4. 中存储对该变量的引用

    如果然后执行john = null,则引用(2)变为null,但对象(1)仍然存在(直到收集垃圾)。

    默认情况下,引用类型按值传递,您可以在Passing Reference-Type Parameters (C# Programming Guide)中阅读。

    这意味着在Execute(User john)中,您在User john中初始化了 Main()副本。如果将该副本设置为null,则原始引用仍然存在,变量也是如此。

    致电Execute(ref User paul)会通过参考传递Main() 中初始化的参考。如果您在该方法中将其设置为null,那么您也会使Main()中的引用归零。

答案 1 :(得分:1)

因为在Execute中,John持有对您在Main(User john)中创建的User对象的引用。在Execute中将John设置为null时,John不再引用在main中创建的对象,而是null。
没有引用,您将获得对传递给函数的对象的引用
使用ref ,您将获得(简化)原始保罗变量在执行中

在没有引用的情况下,您可以将John视为一个指针,该指针保存对存储实际对象的内存区域的引用。如果在指针中放置null,则不会更改实际对象,而是更改指针的内容。在另一种情况下,使用ref从main获取实际的原始变量,因此如果为其指定null,则原始对象将被替换。

答案 2 :(得分:1)

.NET中的类是引用类型。特别是,这意味着,当您定义方法参数时,如下所示:

User John

引用传递给对象。即,John是对内存位置的引用,它由类型为User的实例占用。

使用John进行的任何更改都将修改由John参数引用的对象,但您无法更改此参数引用的内存位置。

另一方面,这个:

ref User Paul

声明对对象的引用的引用。主要区别在于您可以更改由Paul引用的对象,以及,更改由{引用的内存位置(或简单的内存中的地址)。 {1}}变量。

术语"改变"这意味着"影响到来电者"。在方法内部,您可以轻松修改Paul参数的内存位置,但调用者不会看到此修改。

分配John不会破坏对象实例。请注意,我们在托管环境中 - 只有GC决定是否释放内存。通过分配您刚定义的null,您是否仍然可以使用任何变量访问该对象,或者您可以。

答案 3 :(得分:0)

C#中的对象总是通过引用传递 - 没有传递对象的整个副本。即使是原始变量john也只是对象的引用。

因此,当Execute()更新John时,它会更新John的原始(仅)副本。因此,“John”将在第二行输出中打印出来。

当Execute()使John为空时,它只是将其对John的本地引用置空。 Main()中的变量john保持不变。

使用Paul,您已经传递了对引用的引用 - 对Main中变量john的引用,它本身就是对实际User对象的引用。

当Execute()使该引用为空时,它将使Main中的原始引用为空,因此该对象将从内存中释放。