属性 get 调用何时会创建引用类型的本地副本?如何避免这种情况?
在 fooBase
类中,有 SomeProperty
。在类 barBase
中,我有一个 fooBase
类型的字段:
public class fooBase
{
public object SomeProperty { get; set; }
}
public class barBase
{
protected fooBase _foo;
}
很明显,从 barBase 中我可以通过 _foo.SomeProperty = another;
更改 SomeProperty 。
现在,在派生类 fooChild
中,派生类 barChild
运行一些不重要的逻辑。 barChild 构造函数获取 fooChild 的实例并存储它。
public class fooChild : fooBase { /* someLogic */ }
public class barChild : barBase
{
public barChild(fooChild foo)
{
_foo = foo; // foo of [fooChild] type stored in _foo of [fooBase] type.
}
protected fooChild _getFoo // cast via 'as' to access fooChild logic
{ get { return _foo as fooChild; } }
}
现在要使用 fooChild 的逻辑,我需要将 _foo 作为 fooChild
进行访问(_getFoo
就是这样做的)。
问题:get { return ... as ... }
是否会创建 _foo 的本地副本,以便当我调用 SomeFunction()
在barChild的派生类中,barBase._foo中的属性改变SomeProperty不会发生吗?
public class somewhereElse : barChild
{
public void SomeFunction()
{
_getFoo.SomeProperty = new object();
// now barBase:_foo.SomeProperty is still old object?
}
}
如果是,我该如何避免这种情况?
如果不是,我怎么知道?
In the class fooBase
there is SomeProperty
. In the class barBase
, I have a field of type fooBase
:
public class fooBase
{
public object SomeProperty { get; set; }
}
public class barBase
{
protected fooBase _foo;
}
It's clear that from barBase I can change SomeProperty by _foo.SomeProperty = whatever;
.
Now in the derived class fooChild
there is some unimportant logic on which the derived class barChild
operates. The barChild constructor gets an instance of fooChild and stores it.
public class fooChild : fooBase { /* someLogic */ }
public class barChild : barBase
{
public barChild(fooChild foo)
{
_foo = foo; // foo of [fooChild] type stored in _foo of [fooBase] type.
}
protected fooChild _getFoo // cast via 'as' to access fooChild logic
{ get { return _foo as fooChild; } }
}
Now to use the logic of fooChild, I need to access _foo as fooChild
(which _getFoo
does).
Question: Will the get { return ... as ... }
create a local copy of _foo, so that when I call SomeFunction()
in a derived class of barChild, the property change SomeProperty will not happen in the barBase._foo?
public class somewhereElse : barChild
{
public void SomeFunction()
{
_getFoo.SomeProperty = new object();
// now barBase:_foo.SomeProperty is still old object?
}
}
If yes, how can I avoid that?
If no, how can I tell?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
复制引用类型的唯一时间是当您调用主动进行复制的方法或属性时。 Clone() 是一个明显的例子(有一些例外,对于像字符串这样的不可变类型,Clone() 只返回相同的对象并假装它是一个新对象是安全的,因为任何东西都不能改变)。
as
始终是身份转换。x = obj as T
相当于:我有
(T)(object)
而不仅仅是(T)
的原因是有时将存在用于在两种类型之间进行转换的隐式转换运算符,并且可能创建一个新对象。与object
之间的转换不会(除非有人愚蠢地使用了强制转换运算符 - 我很确定编译器会阻止他们,如果他们那么愚蠢,但这是如此愚蠢的情况,我不能不用担心测试,只是不要在对象之间编写强制转换)。如果您想测试一个对象是否与另一个对象相同,请使用ReferenceEquals,即使 Equals 被覆盖,或者参数是装箱值类型,它也仅比较标识。
The only time a reference type is copied is when you call a method or property that actively makes a copy. Clone() being the obvious example (with some exceptions, with an immutable type like string it's safe for Clone() to just return the same object and pretend its a new one, as nothing can change either).
as
is always an identity cast.x = obj as T
is equivalent to:The reason I have
(T)(object)
there instead of just(T)
is that sometimes an implicit cast operator will exist for casting between two types, and that may create a new object. Casting to and fromobject
won't (unless someone's been foolish with cast operators - I'm pretty sure the compiler will stop them if they are that foolish, but it's so silly a case I can't be bothered testing, just don't write casts to and from object).If you want to test if an object is the same as another object use
ReferenceEquals
, this compares solely for identity, even if Equals is overridden, or the arguments are boxed value types.“as”关键字永远不会创建新对象(为什么要这样做?),所以 SomeProperty 是新对象,
这几乎是相同的(并且不会创建新实例)
(如果 myInstance 不是 MySubclass 的类型,则情况不同,在这种情况下,第一行将抛出异常,第二行“as 运算符”将返回 null)
"as" keyword never creates new object (why should it?), so SomeProperty is new object
this is almost the same (and niether will create new instances)
(it's not the same if myInstance is not typeof MySubclass, in that case first line will throw exception and on the second line the "as operator" will return null)