我在设置它之后尝试设置属性的值时遇到了麻烦。我不确定这是否被称为拳击。
无论如何,新变量正在设置,但原始变量没有。我认为新变量只是原始的引用。但是当我检查intellisence / debug观察器时,原始属性仍为空。
这是代码。
// 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 :( :( :(
}
请注意我对tags
和data.TagList
的值的内联评论?有人可以解释一下我做错了什么吗?我认为变量tags
只是一个指向属性data.TagList
的引用指针..但它看起来并非如此。
谢谢你的答案!这是令人尴尬的原因我多年来一直在做这些事情,但仍然忘记/没有注意到这样的简单事情。 (当然,现在让我看到了光明之处。)
Marc得到了积分,因为他的答案(IMO)对我的单个金发脑细胞来说是最简单的。
全部谢谢!
答案 0 :(得分:10)
标签和数据是完全孤立的变量。仅仅因为您将对象分配给tags
,这对变量 data
没有任何影响。
您感到困惑的是,当两个变量指向同一个对象时,对(单个)对象的更改将会通过变量看到。
基本上,如果data
开始非空,则有
在这种情况下,将对象添加到data
或tags
实际上是将对象添加到相同的“列表A”
但是,如果data
开始为null,则您有:
然后指定tags
,给予:
您必须手动将“列表B”分配给data
以使其坚持。
然而,有一种方法可以让它(分配一个接口/对象)起作用: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
}
}
答案 1 :(得分:2)
您需要了解对象引用与变量/属性引用之间的区别。
当您阅读.TagList属性时,您获得的是它存储的引用的副本。假设TagList属性的类型是List<Tag>
,那就是你得到的副本。
重要的是,您现在明白如果TagList已经拥有对现有列表的引用,那么现在您有两个对该列表的引用。一个在TagList属性中,一个在tags变量中。
但是,由于两者都在内存中引用相同的单个列表,如果你向它添加内容,那么无论你如何到达该列表,该列表都将包含新项目。
但是,现在在这里的代码中,您发现包含任何TagList的副本的标记为null,因此您构造一个新列表并将其放入标记中。这使得标签与TagList的不同之处在于TagList仍然保持空引用。标签没有以任何方式链接到TagList属性,对标签的更改不会自动更改TagList。
所以基本上你需要将该引用存储回TagList属性,否则当代码完成执行时它仍然为null。
有关参考如何工作的说明,请参阅我的答案:Understanding pointers。由于参考是心脏指针,相同的解释仍然是正确的。
如果你按照我的解释,你所做的就是在一张纸上写下地址的副本,写在另一张纸上,即。复制了它。一旦您发现您的复印纸是空的,您就在复印纸上写下新建房屋的地址,但原始文件仍然是空的。
答案 2 :(得分:1)
您正在重新设置引用(即tags
),但这不会更改TagList
属性的值。对于此类分配,这始终是正确的。只有对内容的更改(即您的Add
调用)才会在同一对象的引用中进行。
为此,您需要将新的List<>
实例分配给原始属性和您的tags
变量。然后你可以使用所需的结果进行操作。
顺便说一句,我认为IsNullOrEmpty
是一种扩展方法?
答案 3 :(得分:0)
您已从TagList
媒体资源中读取。这使tags
保持与TagList
相同的值。但tags
不是TagList
的别名。改变其中任何一个都不会改变另一个。您为本地tags
变量分配了一个新值,但这不会更改以前用于初始化该变量的属性。您需要将新的tags
值返回分配到TagList
。