在方法中实例化一个类

时间:2017-10-03 00:49:06

标签: c# oop c#-4.0 c#-3.0

是否可以这样做

void Instantiate(Class c) {
   c = new Class();
}

Class c1 = null;
Instantiate(c1);
c1.property .....gives me null reference exception

可以在方法中实例化一个类并在其外部使用吗?

2 个答案:

答案 0 :(得分:0)

是的,但您必须通过引用传递参数:

void Instantiate(ref Class c) {
   c = new Class();
}

Class c1 = null;
Instantiate(ref c1);

默认情况下,所有参数都按值传递。在引用类型的情况下,引用是传递的值。因此,如果您更改对象的内部状态,它将在方法外部可见(例如,将元素添加到列表中)。但是,但是您无法替换整个实例 - 调用者无法看到更改。

我们假设你有List<T>

var myList = new List<T>();

让我们假设它已在某个内存位置0x1234初始化。现在,您将其传递给采用List<T>

的方法
void doSomethingWithAList(List<T> list)
{
}

以后

doSomethingWithAList(myList);

此时,方法外的myListlist内的doSomethingWithAList指向相同的地址(0x1234)。如果您执行list.Add(default(T))并稍后致电myList.Lenghth,您将返回1,因为他们都指向0x1234处的同一个对象。

但是,如果在doSomethingWithAList内,您为list分配了一个新列表:

void doSomethingWithAList(List<T> list)
{
    list = new List<T>();
}

list点在该新对象上。 myList仍指向0x1234

一旦您通过引用更新了List<T>方法,更新list点也会更新myList指向方法之外的内容。

答案 1 :(得分:0)

我认为混淆是所有参数都通过值传递给另一个方法。因此,当您将引用类型传递给方法时,引用的副本将传递给方法。

在您的示例中,c1最初指向null。当你调用instantiate,一个c1的副本时,我将它命名为c1_(它指向null)并且c1_被传递给方法Instantiate,而不是c1。

有两种方法可以使您的代码正常工作。第一种方法是使用ref关键字。 ref关键字将允许c1传递给方法。

void Instantiate(ref Class c) {
   c = new Class();
}

并将其称为

Instantiate(ref c1);

我建议您在此特定示例中使用返回类型。

Class Instantiate() {
   return new Class();
}

您可以按照以下方式使用该方法。

Class c1 = Instantiate();