I'm having trouble trying to set the value of a property after i cast it. I'm not sure if this is called boxing.
在我投射之后,我无法设置属性的值。我不确定这是否称为拳击。
Anyways, the new variable is getting set, but the original is not. I thought the new variable is just a reference to the original. But when i check the intellisence/debug watcher, the original property is still null.
无论如何,新的变量正在设置,但原始的不是。我认为新变量只是对原始变量的引用。但是当我检查intellisence / debug观察器时,原始属性仍为null。
here's the code.
这是代码。
// NOTE: data is either a Foo || FooFoo || FooBar, at this point.
// only Foo impliments ITagElement.
if (data is ITagElement)
{
var tags = ((ITagElement)data).TagList;
// At this point, tags == null and data.TagList == null.
if (tags.IsNullOrEmpty())
{
tags = new List<Tag>();
}
tags.Add(new Tag
{
K = xmlReader.GetAttribute("k"),
V = xmlReader.GetAttribute("v")
});
// At this point, Tags.Count == 1 and data.TagList == null :( :( :(
}
Notice my inline comments about the values for tags
and data.TagList
? Can some explain what I have done wrong? I thought the variable tags
is just a reference pointer to the property data.TagList
.. but it looks like it's not.
请注意我对标签和data.TagList的值的内联注释?有人可以解释一下我做错了什么吗?我认为变量标签只是属性data.TagList的引用指针..但它看起来不是。
Update / Answer :)
thanks for the answers guys! it's embarassing cause i've been doing ths stuff for years and still forget/not notice simple things like this. (And of course, makes so much sence now that i see the light).
谢谢你们的答案!这是令人尴尬的原因,我已经做了多年的事情,仍然忘记/没有注意到这样的简单事情。 (当然,现在让我看到了光明)。
Marc got the points because his answer (IMO) was the simplest for my single blond brain cell.
Marc得到了积分,因为他的回答(IMO)对我的单个金发脑细胞来说是最简单的。
Thanks all!
4 个解决方案
#1
Tags and data are completely isolated variables. Just because you assign an object to tags
, this makes no difference to the variable data
.
标签和数据是完全孤立的变量。仅仅因为您将一个对象分配给标签,这对变量数据没有任何影响。
What you are getting confused is that when the two variables point to the same object, then changes to the (single) object will be seen through either variable.
您感到困惑的是,当两个变量指向同一个对象时,将通过任一变量看到对(单个)对象的更改。
Basically, if data
starts non-null, you have
基本上,如果数据开始非空,那么
- data: points to "list A"
- tags: points to "list A"
数据:指向“列表A”
标签:指向“列表A”
In this scenario, adding an object to either data
or tags
is actually adding an object to the same "list A"
在这种情况下,将对象添加到数据或标记实际上是将对象添加到相同的“列表A”
However, if data
starts null, you have:
但是,如果数据开始为null,则您具有:
- data: points to null
- tags: points to null
data:指向null
tags:指向null
You then assign tags
, giving:
然后分配标签,给出:
- data: points to null
- tags: points to "list B"
data:指向null
标签:指向“列表B”
You would have to manually assign the "list B" to data
to make it stick.
您必须手动将“列表B”分配给数据才能使其坚持下去。
There is, however, one way to get it (assigning an interface/object) to work: ref
and generics:
但是,有一种方法可以让它(指定一个接口/对象)工作:ref和泛型:
using System.Collections.Generic;
using System;
class Foo : IBar
{
List<string> list = new List<string>();
public int Count { get { return list.Count; } }
void IBar.Add(string s) { list.Add(s); }
}
interface IBar
{
void Add(string s);
}
static class Program
{
static void Main()
{
Foo foo = null; // note foo starts as null
CreateAndAdd(ref foo, "abc");
Console.WriteLine(foo.Count); // prove non-null and added
}
static void CreateAndAdd<T>(ref T data, string s) where T : IBar, new()
{
if (data == null) { data = new T(); } // create
data.Add(s); // mutate
}
}
#2
You need to understand the difference between a reference to an object, and a reference to a variable/property.
您需要了解对象引用与变量/属性引用之间的区别。
When you read the .TagList property, what you get is a copy of the reference it stores. Assuming the type of the TagList property is List<Tag>
, that's what you get a copy of.
当您阅读.TagList属性时,您获得的是它存储的引用的副本。假设TagList属性的类型是List
It's important that you now understands that if TagList already holds a reference to an existing list, now you have two references to that list. One in the TagList property, and one in your tags variable.
重要的是,您现在明白如果TagList已经拥有对现有列表的引用,那么现在您有两个对该列表的引用。一个在TagList属性中,一个在tags变量中。
But, since both refer to the same, single, list in memory, if you add something to it, then that list will contain the new item, regardless of how you get to that list.
但是,由于两者都在内存中引用相同的单个列表,如果向其中添加内容,则该列表将包含新项目,无论您如何访问该列表。
However, in your code here now, you discover that tags, which holds a copy of whatever TagList held, is null, so you construct a new list and put that into tags. This makes tags differ from TagList in that TagList still holds a null reference. tags isn't linked in any way to the TagList property, and changes to tags won't automatically change TagList.
但是,现在在这里的代码中,您发现包含任何TagList的副本的标记为null,因此您构造一个新列表并将其放入标记中。这使得标签与TagList的不同之处在于TagList仍然保持空引用。标签没有以任何方式链接到TagList属性,对标签的更改不会自动更改TagList。
So basically you need to store that reference back into the TagList property, otherwise it will still be null when your code finishes executing.
所以基本上你需要将该引用存储回TagList属性,否则当代码完成执行时它仍然为null。
For an explanation of how references work, see my answer here: Understanding pointers. Since references are at heart pointers, the same explanation is still true.
有关引用如何工作的解释,请参阅我的答案:理解指针。由于引用是心脏指针,相同的解释仍然是正确的。
What you have done, if you follow my explanation, is written down a copy of the address on one piece of paper, onto another piece of paper, ie. copied it. Once you discover that your copy-paper is empty, you write the address of a newly constructed house on your copy-paper, but the original paper is still empty.
如果按照我的解释,你所做的就是在一张纸上写下地址的副本,写在另一张纸上,即。复制它。一旦发现您的复印纸是空的,您就可以在复印纸上写下新建房屋的地址,但原始纸张仍然是空的。
#3
You're re-setting your reference (i.e. tags
) but this doesn't change the value of the TagList
property. This is always true for such assignments. Only changes to the content (i.e. your Add
calls) are carried across references for the same object.
您正在重新设置引用(即标记),但这不会更改TagList属性的值。对于此类任务,这始终是正确的。只对内容的更改(即您的Add调用)在同一对象的引用之间进行。
To make it so, you need to assign a new List<>
instance to the original property and your tags
variable. Then you can manipulate either with the desired result.
为此,您需要为原始属性和tags变量分配一个新的List <>实例。然后您可以使用所需的结果进行操作。
By the way, I presume IsNullOrEmpty
is an extension method?
顺便说一句,我认为IsNullOrEmpty是一个扩展方法?
#4
You have read from the TagList
property. That makes tags
hold the same value as TagList
. But tags
is not an alias for TagList
. Changing either of them will not change the other. You assign a new value to the local tags
variable, but that doesn't change the property you used to initialize that variable before. You need to assign the new tags
value back into TagList
.
您已从TagList属性中读取。这使得标签与TagList保持相同的值。但标签不是TagList的别名。改变其中任何一个都不会改变另一个。您为本地标记变量分配了一个新值,但这不会更改以前用于初始化该变量的属性。您需要将新标记值分配回TagList。
#1
Tags and data are completely isolated variables. Just because you assign an object to tags
, this makes no difference to the variable data
.
标签和数据是完全孤立的变量。仅仅因为您将一个对象分配给标签,这对变量数据没有任何影响。
What you are getting confused is that when the two variables point to the same object, then changes to the (single) object will be seen through either variable.
您感到困惑的是,当两个变量指向同一个对象时,将通过任一变量看到对(单个)对象的更改。
Basically, if data
starts non-null, you have
基本上,如果数据开始非空,那么
- data: points to "list A"
- tags: points to "list A"
数据:指向“列表A”
标签:指向“列表A”
In this scenario, adding an object to either data
or tags
is actually adding an object to the same "list A"
在这种情况下,将对象添加到数据或标记实际上是将对象添加到相同的“列表A”
However, if data
starts null, you have:
但是,如果数据开始为null,则您具有:
- data: points to null
- tags: points to null
data:指向null
tags:指向null
You then assign tags
, giving:
然后分配标签,给出:
- data: points to null
- tags: points to "list B"
data:指向null
标签:指向“列表B”
You would have to manually assign the "list B" to data
to make it stick.
您必须手动将“列表B”分配给数据才能使其坚持下去。
There is, however, one way to get it (assigning an interface/object) to work: ref
and generics:
但是,有一种方法可以让它(指定一个接口/对象)工作:ref和泛型:
using System.Collections.Generic;
using System;
class Foo : IBar
{
List<string> list = new List<string>();
public int Count { get { return list.Count; } }
void IBar.Add(string s) { list.Add(s); }
}
interface IBar
{
void Add(string s);
}
static class Program
{
static void Main()
{
Foo foo = null; // note foo starts as null
CreateAndAdd(ref foo, "abc");
Console.WriteLine(foo.Count); // prove non-null and added
}
static void CreateAndAdd<T>(ref T data, string s) where T : IBar, new()
{
if (data == null) { data = new T(); } // create
data.Add(s); // mutate
}
}
#2
You need to understand the difference between a reference to an object, and a reference to a variable/property.
您需要了解对象引用与变量/属性引用之间的区别。
When you read the .TagList property, what you get is a copy of the reference it stores. Assuming the type of the TagList property is List<Tag>
, that's what you get a copy of.
当您阅读.TagList属性时,您获得的是它存储的引用的副本。假设TagList属性的类型是List
It's important that you now understands that if TagList already holds a reference to an existing list, now you have two references to that list. One in the TagList property, and one in your tags variable.
重要的是,您现在明白如果TagList已经拥有对现有列表的引用,那么现在您有两个对该列表的引用。一个在TagList属性中,一个在tags变量中。
But, since both refer to the same, single, list in memory, if you add something to it, then that list will contain the new item, regardless of how you get to that list.
但是,由于两者都在内存中引用相同的单个列表,如果向其中添加内容,则该列表将包含新项目,无论您如何访问该列表。
However, in your code here now, you discover that tags, which holds a copy of whatever TagList held, is null, so you construct a new list and put that into tags. This makes tags differ from TagList in that TagList still holds a null reference. tags isn't linked in any way to the TagList property, and changes to tags won't automatically change TagList.
但是,现在在这里的代码中,您发现包含任何TagList的副本的标记为null,因此您构造一个新列表并将其放入标记中。这使得标签与TagList的不同之处在于TagList仍然保持空引用。标签没有以任何方式链接到TagList属性,对标签的更改不会自动更改TagList。
So basically you need to store that reference back into the TagList property, otherwise it will still be null when your code finishes executing.
所以基本上你需要将该引用存储回TagList属性,否则当代码完成执行时它仍然为null。
For an explanation of how references work, see my answer here: Understanding pointers. Since references are at heart pointers, the same explanation is still true.
有关引用如何工作的解释,请参阅我的答案:理解指针。由于引用是心脏指针,相同的解释仍然是正确的。
What you have done, if you follow my explanation, is written down a copy of the address on one piece of paper, onto another piece of paper, ie. copied it. Once you discover that your copy-paper is empty, you write the address of a newly constructed house on your copy-paper, but the original paper is still empty.
如果按照我的解释,你所做的就是在一张纸上写下地址的副本,写在另一张纸上,即。复制它。一旦发现您的复印纸是空的,您就可以在复印纸上写下新建房屋的地址,但原始纸张仍然是空的。
#3
You're re-setting your reference (i.e. tags
) but this doesn't change the value of the TagList
property. This is always true for such assignments. Only changes to the content (i.e. your Add
calls) are carried across references for the same object.
您正在重新设置引用(即标记),但这不会更改TagList属性的值。对于此类任务,这始终是正确的。只对内容的更改(即您的Add调用)在同一对象的引用之间进行。
To make it so, you need to assign a new List<>
instance to the original property and your tags
variable. Then you can manipulate either with the desired result.
为此,您需要为原始属性和tags变量分配一个新的List <>实例。然后您可以使用所需的结果进行操作。
By the way, I presume IsNullOrEmpty
is an extension method?
顺便说一句,我认为IsNullOrEmpty是一个扩展方法?
#4
You have read from the TagList
property. That makes tags
hold the same value as TagList
. But tags
is not an alias for TagList
. Changing either of them will not change the other. You assign a new value to the local tags
variable, but that doesn't change the property you used to initialize that variable before. You need to assign the new tags
value back into TagList
.
您已从TagList属性中读取。这使得标签与TagList保持相同的值。但标签不是TagList的别名。改变其中任何一个都不会改变另一个。您为本地标记变量分配了一个新值,但这不会更改以前用于初始化该变量的属性。您需要将新标记值分配回TagList。