在对象初始值设定项中使用后清除变量也会清除对象的属性吗?

时间:2012-07-12 16:25:42

标签: c# object

为什么此代码运行后Tags的{​​{1}}属性为空?

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 的部分答案引用了原始代码。

3 个答案:

答案 0 :(得分:5)

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

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

Tags = new List<string>(tags);

答案 1 :(得分:1)

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

当您撰写Tags = tags时,您实际上是将Tags 指向指向tags的同一个实例。

这就是为什么当您清除tags时,Tags也被清除,因为它是相同的对象引用

答案 2 :(得分:1)

  

标签和标题是否通过引用传递到此处?

然而,混淆(基于评论)似乎是由于TagsTitle在您的代码中的行为方式不同。

执行此操作时TagsTitle之间的行为差​​异:

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

是因为在第一种情况下,您要为标题分配一个全新的实例。但是,当您致电tags.Clear()时,您正在改变现有实例,这是&#34;共享&#34;使用Tags内的book[0]属性(因为List<string>是一个类,并且具有引用类型语义)。