【问题标题】:Object initialized in other class's method isn't referenced by calling method in C#在其他类的方法中初始化的对象不被 C# 中的调用方法引用
【发布时间】:2025-12-06 02:25:01
【问题描述】:

我有一个类,我在其中声明一个对象,但不初始化该对象。然后我将对象传递给另一个类中的方法进行初始化。我期望发生的是调用类中的对象现在将具有对初始化对象的引用,但它是空的。

这是我的意思的一个例子:

class MainClass
{
    ObjectA foo;

    OtherClass.InitializeObjectA(foo);

    // why is foo null over here?
}

class OtherClass
{
    public static void InitializeObjectA(ObjectA device)
    {
        device = new ObjectA();
    }
}

我的问题是,当我在调用InitializeObjectA() 后尝试使用 foo 时,它仍然指向 null!如果我将 InitializeObjectA() 更改为 out ObjectA device 它可以工作。谁能解释为什么需要这样做?

【问题讨论】:

标签: c# objectinstantiation


【解决方案1】:

如果你想让这个工作,你需要通过引用传递:

public static void InitializeObjectA(ref ObjectA device)
{

或者:

public static void InitializeObjectA(out ObjectA device)
{

否则,InitializeObjectA 会将 device 参数设置为 new ObjectA(),但这不会影响调用者,因为默认情况下,引用是按值传递的

请注意,如果您只是尝试初始化,返回一个实例而不是 void 通常是更好的处理方式:

public static ObjectA InitializeObjectA()
{
     return new ObjectA();
}

这避免了使用refout 传递的需要。

【讨论】:

  • 或者,直接返回 ObjectA
  • 谢谢,我想我的困惑是我虽然所有对象都是通过引用传递的。
  • @w1res 否 - 类是引用类型,因此它们是按值传递的引用。这意味着您可以更改类本身内部的值,但您不能重新分配对象引用并将其传回。
  • @STW 把它捐给你选择的慈善机构;)
  • 隐藏我的无知,删除我的 cmets :) -- 但是美元应该被捐赠!
【解决方案2】:

一个类是一个引用类型,你将 foo 的地址作为参数(副本)传递,在你更改副本中,但新地址不会被设置回原来的 foo。这只能通过 outref 关键字来完成。

【讨论】:

  • 如果 foo 在发送之前已经被实例化,那么改变一些关于 foo 的东西就可以了。在这种情况下,他没有提及开始,因此也没有提及通过。
  • @Rake36,即使 foo 有一个实例,在调用方法之前,原始实例指针也会被压入堆栈,调用后它会被弹回。因此,如果您更改指针,它将引用原始指针。如果没有 refout,则无法更改参数的实例。
  • 如果是值类型,则为真,但如果您要更改 ObjectA 的属性,那肯定是允许的。这是我试图提出的唯一观点。 “改变”这个词在这里具有误导性。
【解决方案3】:

创建名为 foo 的 ObjectA 实例的最简单方法是返回实例以分配给变量

class MainClass
{
    ObjectA foo = OtherClass.InitializeObjectA();
}

class OtherClass
{
    public static ObjectA InitializeObjectA()
    {
        return new ObjectA();
    }
}

【讨论】:

  • 秒杀我:)
【解决方案4】:

为什么不让 Initialize 方法返回创建的对象?

class MainClass
{
    var foo = OtherClass.InitializeObjectA(foo);
}

class OtherClass
{
    public static ObjectA InitializeObjectA(ObjectA device)
    {
        return new ObjectA();
    }
}

【讨论】:

  • 我没有在问题中提到这一点,但在我的实际代码中我已经返回了一个布尔值。
  • 如果方法的主要职责是创建和初始化对象,为什么不返回呢?通过使用引用或 Out 参数来执行此操作意味着此方法具有副作用 (*.com/questions/810289/…)。副作用使调试和维护更加困难,应该避免。
【解决方案5】:

据我了解,C# 编译器实际上并没有像那样为您初始化变量。我什至无法在 Visual Studio 2010 中编译此代码,因为将未初始化的参数传递给函数是错误的。

你想要:

ObjectA foo = null;

无论如何,我认为您正在尝试做的是,C# 不像在 Java 中那样为您做这件事。这仍然没有得到我认为你想要实现的行为,这可能最好通过将你的代码重构为类似的东西来实现

ObjectA foo = InitializeObjectA()

public static ObjectA InitializeObjectA(){
    return new ObjectA();
}

或者,您可以使用按引用传递,将引用(或如果您熟悉它的指针)传递给函数,因此对该引用所做的更改会反映在函数范围之外。

【讨论】:

  • 或者:ObjectA foo = new ObjectA();
  • 是的。我只是认为他出于某种原因想使用 InitializeObject 方法
【解决方案6】:

那是因为当你这样做时

device = new ObjectA();

您正在将对象设置为新对象,在内存中具有不同的引用。

你应该这样做:

class MainClass
{
    ObjectA foo = OtherClass.InitializeObjectA(foo);
}

class OtherClass
{
    public static ObjectA InitializeObjectA(ObjectA device)
    {
        return = new ObjectA();
    }
}

或者改为

class MainClass
{
    ObjectA foo = null;
    OtherClass.InitializeObjectA(out foo);
}

class OtherClass
{
    public static void InitializeObjectA(out ObjectA device)
    {
        device = new ObjectA();
    }
}

有关为什么会发生这种情况的更多信息,请访问here

【讨论】: