3

为什么这段代码运行后Tags属性为Book空?

class Program
{
    static void Main(string[] args)
    {
        List<Book> books = new List<Book>();
        List<String> tags = new List<String> {"tag1", "tag2", "tag3"};
        String title = "a title";
        books.Add(new Book
        {
            Title = title,
            Author = "an author",
            Tags = tags
        });
        Console.WriteLine("(" + title + ")");
        Console.WriteLine((books[0]).Tags.Count());

        title = String.Empty;
        tags.Clear();

        Console.WriteLine("(" + title + ")");
        Console.WriteLine((books[0]).Tags.Count());
    }
}

代码Book

public class Book
{
    public String Title { get; set; }
    public String Author { get; set; }
    public List<String> Tags { get; set; }
}

运行此代码输出

("a title")
3
()
0

是否在tags这里title通过引用传递?重命名相应的属性会产生相同的输出。

编辑:

我刚刚意识到我的意思是让每个Console.WriteLine语句都引用对象,而不仅仅是标签。我的意思是:

Book aBook = books[0];
Console.WriteLine("(" + aBook.Title + ")");
Console.WriteLine(aBook.Tags.Count());

title = String.Empty;
tags.Clear();

Console.WriteLine("(" + aBook.Title + ")");
Console.WriteLine(aBook.Tags.Count());

正如预期的那样,输出:

("a title")
3
("a title")
0

但是由于我在最初的问题中犯了一个错误,因此我将其保留原样,因为所引用的答案部分title引用了原始代码。

4

3 回答 3

5

List<T>是一个引用类型,所以是的,你在这里得到引用语义。

如果您希望它们独立,则需要为该属性分配一份副本。tags

Tags = new List<string>(tags);
于 2012-07-12T16:27:23.790 回答
1

Tags您的Book对象的属性引用与您在第二行代码 ( )中创建的列表相同的对象实例。List<String> tags = new List<String> {"tag1", "tag2", "tag3"};

当你写的时候Tags = tags,你实际上是在说 thatTags 指向同一个实例tags

这就是为什么当你清除时tagsTags也被清除,因为它是同一个对象引用

于 2012-07-12T16:29:40.573 回答
1

标签和标题是否在这里通过引用传递?

是的。

但是,混淆(基于注释)似乎是由于代码中的方式TagsTitle行为不同造成的。

Tags执行时和执行时的行为差异Title

title = String.Empty;
tags.Clear();

是因为在第一种情况下,您正在为标题分配一个全新的实例。但是,当您调用tags.Clear()时,您正在改变现有的 instance,它与Tags内部的属性“共享” book[0](因为List<string>它是一个类并且具有引用类型语义)。

于 2012-07-12T16:31:28.717 回答