【问题标题】:object is really reference type?对象真的是引用类型吗?
【发布时间】:2013-02-22 11:34:07
【问题描述】:

据我所知ClassObject 是引用类型。

我有以下方法来更改值

public void ChangeValue(MyClass classobj)
{
    classobj.Number = classobj.Number*2;
}

我调用该方法将值加倍

var myClass=new MyClass();
int myNumber = 10;
myClass.Number = myNumber;
ChangeValue(myClass);

它会返回 20,这很好,因为您可以将其解释为当您创建类的对象然后它将引用传递给方法并更新引用值。

但我的问题是为什么它不会发生在 Object 类型中。换句话说,为什么当我制作对象并为其分配一些值时,如下所示

 object myObject = new object();
 string sometext  = "Some object value";
 myObject = sometext;
 ChangeValue(myObject)

方法执行后不会改变值

public void ChangeValue(object objectValue)
{
    objectValue = null;
}

我知道方法的参数是值类型,但不能理解它对于两个引用类型有不同的行为。

【问题讨论】:

标签: c# types reference-type


【解决方案1】:

您实际上在这里做了两件不同的事情。 Object 和您的 MyClass 确实都是引用类型,这意味着您将对实际对象的引用传递给 ChangeValue 方法。但是,您在方法中看到的引用是调用者持有的引用的副本。它们指向同一个对象,因此当您在方法中操作对象时,方法的调用者可以看到您的更改,但对方法内部实际引用的更改只会影响方法本身。

总结一下,对象是通过引用传递的,但那些引用是通过传递的。

在你的方法中

public void ChangeValue(object objectValue)
{
    objectValue = null;
}

您实际上正在做的是重新分配引用objectValue,并且该引用是调用者拥有的名为myObject 的引用的副本。因为方法只有一个副本,所以根本不会影响调用者的引用。

有一种方法可以做到这一点,你必须通过引用传递引用。这总是让我头疼,但这就是 ref 关键字的用途。

public void ChangeValue(ref object objectValue)
{
    objectValue = null; // this is the SAME reference as the caller has, so the caller will see this change
}

但是,它也必须这样调用:

ChangeValue(ref myObject);

因此在调用站点很明显它可能会返回指向不同的对象。了解这一点很重要,因为如果引用意外指向不同的对象,您可能仍然有依赖于旧值的东西并最终陷入可怕的混乱之中。

【讨论】:

  • 我明白你的意思,这确实是对的。我的问题伴随着您的解释,即“为什么 myClass 的值在 ChangeValue(MyClass classobj) 中发生变化?”想象一下 myclass 引用的副本来到该方法,我更改了 classobj.Number = 0;那么它将如何通知调用者此更改?
  • 这不是告诉调用者有关更改的问题。调用者和方法都看到并修改了同一个对象,因为它们都有对它的引用。如果调用者在方法运行后查看对象,它将看到更改,因为该方法更改了同一个对象。
【解决方案2】:

您通过值将objectValue 传递给ChangeValue(object objectValue),该值是一个引用。然后你改变这个值,而不是myObject的值。

您必须将其作为ChangeValue(ref object objectValue) 传递才能真正通过引用传递引用的值。

【讨论】:

  • 我对 myclass object 做了同样的事情,我将它作为对象,然后将它传递给 Changevalue(MyClass objClass),这个值是一个引用类型。然后我将它的值更改为 20,它也反映了我的调用者对象值。那为什么它适用于 myClass 对象?
  • @wikinevis,因为你实际上并没有改变 myClass 的值(myClass 的值是一个引用),所以你改变了 myClass 引用的对象的值。跨度>
【解决方案3】:

这不是一种不同的行为,你在做不同的事情

这将与您的 object 示例完全相同:

    public void ChangeValue(MyClass classobj)
    {
        classobj = null;
    }

这将作为您的第一个示例(假设您将传递 MyClass 实例):

   public void ChangeValue(object objectValue)
    {
        ((MyClass)objectValue).Number *= 2;
    }

这里真正发生的是,当您分配参数(而不是参数的属性或字段)时,您只是在更改该参数的值。调用代码中的原始值和变量保持不变。

同样的情况发生在这里:

MyClass a = new MyClass();
MyClass b = a;
a = null;
// b still contains the value created in the first line

简单来说,引用变量保存的是实际值的指针(内存地址)。 通过更改变量的值,您可以使其指向不同的对象或 null。 但是,当您执行 a.field=2 时,这意味着您正在获取 a 所引用的对象并更改它的 field 成员值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-14
    • 1970-01-01
    • 2010-12-08
    • 2011-06-11
    • 2015-07-10
    • 2011-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多