.net 为什么不设置此属性?

.net 为什么不设置此属性?,.net,.net,在强制转换属性后,尝试设置属性的值时遇到问题。我不确定这是否叫做拳击 无论如何,新变量正在设置中,但原始变量尚未设置。我认为新变量只是对原始变量的引用。但是当我检查intellisence/debug watcher时,原始属性仍然为null 这是密码 // NOTE: data is either a Foo || FooFoo || FooBar, at this point. // only Foo impliments ITagElement. if (data is ITa

在强制转换属性后,尝试设置属性的值时遇到问题。我不确定这是否叫做拳击

无论如何,新变量正在设置中,但原始变量尚未设置。我认为新变量只是对原始变量的引用。但是当我检查intellisence/debug watcher时,原始属性仍然为null

这是密码

// 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 :( :( :(
}
注意我关于标记和data.TagList的值的内联注释吗?有人能解释一下我做错了什么吗?我认为变量标记只是指向property data.TagList的引用指针。。但看起来不是

更新/答复: 谢谢你们的回答,伙计们!这让我很尴尬,因为我已经做了很多年了,但仍然忘记/没有注意到像这样简单的事情。当然,现在我看到了光明,这是非常有意义的

马克得到了分数,因为他的答案对我的单个金发脑细胞来说是最简单的


谢谢大家

您已从标记列表属性中读取。这使得标记与标记列表具有相同的值。但标记不是标记列表的别名。改变其中一个不会改变另一个。可以为local tags变量指定一个新值,但这不会更改之前用于初始化该变量的属性。您需要将新标记值重新分配到标记列表中。

您已从标记列表属性中读取。这使得标记与标记列表具有相同的值。但标记不是标记列表的别名。改变其中一个不会改变另一个。可以为local tags变量指定一个新值,但这不会更改之前用于初始化该变量的属性。您需要将新的标记值重新分配到标记列表中。

标记和数据是完全隔离的变量。仅仅因为将对象指定给标记,这对变量数据没有影响

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

基本上,如果数据以非null开头,则

数据:指向列表A的点 标记:指向列表的点 在这种情况下,将对象添加到数据或标记实际上就是将对象添加到同一列表中

但是,如果数据开始为空,则您有:

数据:指向null 标记:指向null 然后指定标记,给出:

数据:指向null 标签:指向列表B的点 您必须手动将列表B分配给数据以使其保持不变

但是,有一种方法可以让它分配一个接口/对象来工作: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
    }
}

标记和数据是完全隔离的变量。仅仅因为将对象指定给标记,这对变量数据没有影响

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

基本上,如果数据以非null开头,则

数据:指向列表A的点 标记:指向列表的点 在这种情况下,将对象添加到数据或标记实际上就是将对象添加到同一列表中

但是,如果数据开始为空,则您有:

数据:指向null 标记:指向null 然后指定标记,给出:

数据:指向null 标签:指向列表B的点 您必须手动将列表B分配给数据以使其保持不变

但是,有一种方法可以让它分配一个接口/对象来工作: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
    }
}

您正在设置引用,即标记,但这不会更改标记列表属性的值。对于这样的任务,这总是正确的。只有对内容的更改(即添加调用)才会跨同一对象的引用进行

要做到这一点,需要为原始属性和tags变量指定一个新的列表实例。然后,您可以使用所需的结果对其中任何一个进行操作


顺便说一下,我假定IsNullOrEmpty是一种扩展方法?

您正在设置引用,即标记,但这不会更改标记列表属性的值。对于这样的任务,这总是正确的。只有对内容的更改(即添加调用)才会跨同一对象的引用进行

要做到这一点,需要为原始属性和tags变量指定一个新的列表实例。然后,您可以使用所需的结果对其中任何一个进行操作


顺便说一下,我假定IsNullOrEmpty是一种扩展方法?

您需要了解对象引用和变量/属性引用之间的区别

当您读取.TagList属性时,您得到的是它存储的引用的副本。假设TagList属性的类型为List,则您将获得其副本

重要的是,您现在了解到,如果标记列表已经包含对现有列表的引用,那么现在您有两个对该列表的引用。一个在TagList属性中,一个在tags变量中

但是,由于两者都指同一个单一的列表 在内存中,如果您向其中添加了一些内容,那么该列表将包含新项目,而不管您如何进入该列表

然而,在这里的代码中,您发现标记(它包含标记列表所包含的任何内容的副本)为空,因此您构建了一个新的列表并将其放入标记中。这使得标记不同于标记列表,因为标记列表仍然保持空引用。标记不会以任何方式链接到标记列表属性,对标记的更改不会自动更改标记列表

因此,基本上您需要将该引用存储回TagList属性中,否则在代码完成执行时它仍然为null

有关引用如何工作的解释,请参见我的回答:。由于引用是核心指针,同样的解释仍然正确


如果你听我的解释,你所做的就是把地址的副本写在一张纸上,再写在另一张纸上。一旦你发现你的复印纸是空的,你就在复印纸上写下新建房屋的地址,但原来的复印纸仍然是空的。

你需要理解对对象的引用和对变量/属性的引用之间的区别

当您读取.TagList属性时,您得到的是它存储的引用的副本。假设TagList属性的类型为List,则您将获得其副本

重要的是,您现在了解到,如果标记列表已经包含对现有列表的引用,那么现在您有两个对该列表的引用。一个在TagList属性中,一个在tags变量中

但是,由于两者都指向内存中相同的、单一的列表,如果您向其中添加了一些内容,那么该列表将包含新项,而不管您如何访问该列表

然而,在这里的代码中,您发现标记(它包含标记列表所包含的任何内容的副本)为空,因此您构建了一个新的列表并将其放入标记中。这使得标记不同于标记列表,因为标记列表仍然保持空引用。标记不会以任何方式链接到标记列表属性,对标记的更改不会自动更改标记列表

因此,基本上您需要将该引用存储回TagList属性中,否则在代码完成执行时它仍然为null

有关引用如何工作的解释,请参见我的回答:。由于引用是核心指针,同样的解释仍然正确


如果你听我的解释,你所做的就是把地址的副本写在一张纸上,再写在另一张纸上。一旦你发现你的复印纸是空的,你就在复印纸上写下一栋新建房屋的地址,但原来的那张纸仍然是空的。

看看刚刚添加的泛型示例——新添加的内容可能也很有意思。也就是说,我不喜欢实例化对象,例如,如果对象可能不被使用,list=newlist。我喜欢空的。我在最后一个可能的时刻进行了实例化,但这只是模式:重点是,ref+泛型的使用很时髦!再看一下刚刚添加的泛型示例——新添加的内容可能会很有趣,也很有意义。也就是说,我不喜欢实例化对象,例如,如果对象可能不被使用,list=newlist。我喜欢空的。我在最后一个可能的时刻进行了实例化,但这只是模式:重点是,ref+泛型的使用很时髦!