为什么这个属性没有设置?

时间:2008-12-20 23:07:53

标签: .net

我在设置它之后尝试设置属性的值时遇到了麻烦。我不确定这是否被称为拳击

无论如何,新变量正在设置,但原始变量没有。我认为新变量只是原始的引用。但是当我检查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 :( :( :(
}

请注意我对tagsdata.TagList的值的内联评论?有人可以解释一下我做错了什么吗?我认为变量tags只是一个指向属性data.TagList的引用指针..但它看起来并非如此。

更新/答案:)

谢谢你的答案!这是令人尴尬的原因我多年来一直在做这些事情,但仍然忘记/没有注意到这样的简单事情。 (当然,现在让我看到了光明之处。)

Marc得到了积分,因为他的答案(IMO)对我的单个金发脑细胞来说是最简单的。

全部谢谢!

4 个答案:

答案 0 :(得分:10)

标签和数据是完全孤立的变量。仅仅因为您将对象分配给tags,这对变量 data没有任何影响。

您感到困惑的是,当两个变量指向同一个对象时,对(单个)对象的更改将会通过变量看到。

基本上,如果data开始非空,则有

  • 数据:指向“列表A”
  • 标签:指向“列表A”

在这种情况下,将对象添加到datatags实际上是将对象添加到相同的“列表A”

但是,如果data开始为null,则您有:

  • 数据:指向null
  • tags:指向null

然后指定tags,给予:

  • 数据:指向null
  • 标签:指向“列表B”

您必须手动将“列表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