对象实际上是引用类型
本文关键字:引用类型 实际上 对象 | 更新日期: 2023-09-27 18:00:47
据我所知,Class
和Object
是引用类型。
我有以下方法来更改值
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;
}
我知道方法的参数是值类型,但不能理解它对两个引用类型有不同的行为。
您实际上在这里做两件不同的事情。Object
和MyClass
实际上都是引用类型,这意味着您将对实际对象的引用传递到ChangeValue
方法中。但是,您在方法内部看到的引用是调用者持有的引用的副本。它们指向同一个对象,因此当您在方法中操作对象时,方法的调用方可以看到您的更改,但对方法内部实际引用的更改只会影响方法本身。
在总结中,对象通过引用传递,但这些引用通过value来传递。
在你的方法
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);
因此,在调用站点上很明显,它可能会指向另一个对象。要知道这一点很重要,因为如果引用意外地指向不同的对象,您可能仍然有依赖于旧值的东西,并最终陷入可怕的混乱。
通过值将objectValue
传递给ChangeValue(object objectValue)
,该值是一个引用。然后更改该值,但不更改myObject
的值。
您必须将其作为ChangeValue(ref object objectValue)
传递,才能逐个引用地实际传递引用的值。
这不是不同的行为,你在做不同的事情
这将与您的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
成员值。