2016-09-16 118 views
1

我从未意识到过这样的问题。如果我传递了一个具有特定类型但尚未实例化的变量,那么它不应该被视为一个指针吗?在这个例子中,为什么如果方法GetEmployee创建一个新的实例,我回到了单击事件的范围时,我得到了空值。传递一个类的变量作为之前定义为null的参数

我知道为了使它工作,我可以将参数定义为ref或out,但Employee是一个最初被定义为null的类,但是当我做新的时候,我会在内存中分配一个空间,不要链接到变量?为什么我以后失去价值?

如果我传递一个对象,那么当我回到click事件的范围时,内部方法中所有修改过的属性将保持不变的情况将完全不同。

这将无法正常工作

protected void btnTest_Click(object sender, System.EventArgs e) 
    { 
     Employee employee = null; 
     bool created = GetEmployee(employee); 
    } 

这将工作

protected void btnTest_Click(object sender, System.EventArgs e) 
    { 
     Employee employee = new Employee(); 
     bool created = GetEmployee(employee); 
    } 

其余

private bool GetEmployee(Employee employee) 
    { 
     if (employee == null) 
     { 
      employee = new Employee(); 

     } 
     employee.ID = 1; 
     employee.Name = "John"; 
     return true; 
    } 

    public class Employee 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
    } 

UPDATE:

的COM把事情稍微折腾一下。这也将失败,因为该对象从未被设置为不同的东西,以空

protected void btnTest_Click(object sender, System.EventArgs e) 
    { 
     int id = 1; 
     Employee employee = this.LoadFromDatabase(id); 
     bool created = GetEmployee(employee); 
    } 

    private Employee LoadFromDatabase(id) 
    { 
     //In the inner service method if it is not found it will return null 
     return Service.Instance.LoadFromDatabase(id); 
    } 

    private bool GetEmployee(Employee employee) 
    { 
     if (employee == null) 
     { 
      employee = new Employee(); 

     } 
     employee.ID = 1; 
     employee.Name = "John"; 
     return true; 
    } 

回答

0

Employee是引用类型,这是什么意思是,它实际上员工数据的地址。

GetEmployee中的employee参数只是该地址的副本。由于您知道地址,因此您可以更改地址上的信息,但因为它只是一个副本,所以您对地址本身做出的任何更改(例如employee = new Employee();)都不会影响您通过的地址。

当您做employee = new Employee();你已经覆盖了复制的地址,新的地址指向一个完全不同的员工在内存中。这就是为什么你没有看到你通过的员工有任何变化。

2

虽然员工的成员可以由调用者修改,但员工本身的引用不能。在C#中传入引用类型参数时,您可以修改该对象的成员并查看调用者中的更改。但是,引用本身是通过值传递的,并且分配给参数不会执行任何操作。做你想做什么,只是返回的员工,而不是错误地试图修改参考:

private Employee GetEmployee(Employee employee) 
{ 
    if (employee == null) 
    { 
     return new Employee() 
     { 
      ID = 1, 
      Name = "John", 
     }; 
    } 

    employee.ID = 1; 
    employee.Name = "John"; 
    return employee; 
} 
+0

https://blogs.msdn.microsoft.com/csharpfaq/2004/03/11/how-are-parameters-passed-in-c-are-they-by-reference-by-value/ – Jakotheshadows

+0

对,在这种情况下,值是引用,你不能改变引用,因此分配某些参数在调用者中没有任何作用。 – Jakotheshadows

+0

我不确定它是如何错误地传递参考的。 REFERENCE是按值传递的。我会编辑我的答案,以明确表示。 – Jakotheshadows

0

当你传递一个引用类型整个方法,一个方法参数将是一个新的参考同一对象,除非您使用ref关键字

public class A {} 

public class B 
{ 
    public void DoStuff(A a) // <--- "a" is a new reference of type A 
    { 
     a = new A(); 
    } 
} 

所以...

调用DoStuff用下面的代码:

A a = null; 
DoStuff(a); 

...会给A类型的空引用DoStuff。也就是说,您不会在方法调用期间使用给定的引用,但参数因此不会将源引用更新为指向新对象。

否则,你将需要使用ref关键字无论是在方法签名,当你的地方把它叫做:

public class B 
{ 
    public void DoStuff(ref A a) // <--- "a" is a new reference of type A 
    { 
     // Now this will affect the reference that was passed 
     // when this method is being called! 
     a = new A(); 
    } 
} 

B b = new B(); 
A a = new A(); 
b.DoStuff(ref a);