简体   繁体   English

c#列表 <string> 分配问题

[英]c# List<string> assignment problem

I'm fairly new to C# so this might be difficult for me to put into words. 我对C#很新,所以这对我来说可能很难说。

I am creating a media application and I have a class (called MediaFile) that contains information about media files (name, size, play count and tags). 我正在创建一个媒体应用程序,我有一个类(称为MediaFile),其中包含有关媒体文件(名称,大小,播放计数和标签)的信息。 These are of string, double, int and List<string> types, respectively. 它们分别是string,double,int和List<string>类型。

I have a list of these objects, so for example to call MediaFile[2].Tags will refer to a list of "tag" strings (related keywords). 我有一个这些对象的列表,例如调用MediaFile[2].Tags将引用“标签”字符串列表(相关关键字)。

The problem I have is that when I ask the user to enter tags for the selected MediaFile, whenever I try to save those tags to that specific object, the tags get saved to every single object. 我遇到的问题是,当我要求用户输入所选MediaFile的标签时,每当我尝试将这些标签保存到该特定对象时,标签就会保存到每个对象中。 The code for the assignment currently looks something like this: 分配的代码目前看起来像这样:

MediaFile[lstLibrary.SelectedIndices[0]].Tags.Add(tempTag);

'tempTag' is a string that I'm trying to add into the list of strings, but like I said - even though only one file is selected, the 'tempTag' string gets added into the list of strings of each MediaFile. 'tempTag'是一个我想要添加到字符串列表中的字符串,但就像我说的那样 - 即使只选择了一个文件,'tempTag'字符串也会被添加到每个 MediaFile的字符串列表中。

Can anyone shed some light on what I'm doing wrong? 有人能说清楚我做错了吗?

Many thanks. 非常感谢。

EDIT: Thanks for all of your responses. 编辑:感谢您的所有回复。 Whenever I create a MediaFile instance I pass new List<string> to the constructor. 每当我创建一个MediaFile实例时,我都会将new List<string>传递给构造函数。 Then later on when I go to change this list of strings I discover all of the MediaFiles seem to have the same string reference. 然后,当我去更改此字符串列表时,我发现所有的MediaFiles似乎都有相同的字符串引用。 Here is the MediaFile class: 这是MediaFile类:

public static List<MediaType> MediaFile = new List<MediaType>();
public class MediaType
    {
        public string Name;
        public string Path;
        public double Size;
        public int Plays;
        public List<string> Tags;

        // Constructor for adding new files
        public MediaType(string path, List<string> tags)
        {
            Path = path;
            Tags = tags;
        }

And after I ask the user to select a file to add to the media library: 在我要求用户选择要添加到媒体库的文件之后:

MediaFile.Add(new MediaType(Path.GetFullPath(file), new List<string>()));

So there are no 'tags' at first, but then later on (and herein lies my problem): 所以最初没有'标签',但后来又没有'标签'(这就是我的问题):

if (tempTag != "")
    MediaFile[lstLibrary.SelectedIndices[0]].Tags.Add(tempTag);
}

Any idea? 任何想法? Apologies this post is so long! 道歉这篇文章太长了!

That suggests you've added the same string reference to all the MediaFiles. 这表明你已经为所有MediaFiles添加了相同的字符串引用。 In other words, you might have done: 换句话说,您可能已经做过:

List<string> tags = new List<string>();

for (int i = 0; i < 100; i++)
{
    MediaFile file = new MediaFile(tags);
    MediaFiles.Add(file);
}

This is very easy to test - just check whether MediaFile[0].Tags == MediaFile[1].Tags - I suspect you'll find that evaluates to True, meaning you're using the same list for both files. 这很容易测试 - 只需检查MediaFile[0].Tags == MediaFile[1].Tags - 我怀疑你会发现评估为True,这意味着你对两个文件使用相同的列表。

Instead, you should create a new List<string> for each MediaFile instance. 相反,您应该为每个MediaFile实例创建一个新的 List<string>

If you could post some code, that would help us to pin down the problem more precisely, of course... 如果您可以发布一些代码,那将有助于我们更准确地确定问题,当然......

看起来您已将所有MediaFiles[i].Tags设置为对列表的同一实例的引用。

Where do you put stuff in MediaFile? 你把什么东西放在MediaFile中? How do you do it? 你怎么做呢?

My guess is that you're inserting the same MediaFile object several time in the list. 我的猜测是你在列表中多次插入相同的MediaFile对象。 So, when you modify one, you end up modifying all of them because, after all, they are the same object. 因此,当您修改一个时,最终会修改所有这些,因为它们毕竟是同一个对象。

听起来您已经将列表中的所有对象设置为使用标签列表的相同实例

I suspect that you're initialising your objects incorrectly. 我怀疑你错误地初始化你的对象。 You're probably (effectively) creating them like this: 你可能(有效地)像这样创建它们:

List<string> tags = new List<string>();

MediaFile m1 = new MediaFile();
m1.Tags = tags;

MediaFile m2 = new MediaFile();
m2.Tags = tags;

That is, the Tags property of each MediaFile refers to the same actual List<string> object. 也就是说,每个MediaFile的Tags属性引用相同的实际List<string>对象。 Thus, when you add a string to m1.Tags, you're also adding it to m2.Tags. 因此,当您向m1.Tags添加字符串时,您还将其添加到m2.Tags。

What you want to do instead is: 你想要做的是:

MediaFile m1 = new MediaFile();
m1.Tags = new List<string>();

MediaFile m2 = new MediaFile();
m2.Tags = new List<string>();

Does your Tags property have a set accessor? 您的Tags属性是否具有set访问器?

Or do you have code that looks (something) like this? 或者你有代码看起来像这样的东西?

var tags = new List<string>();
for (int i = 0; i < MediaFile.Count; ++i)
{
    MediaFile[0] = new MediaFile(tags);
}

If so then each of your MediaFile instances is sharing the same internal List<string> . 如果是,则每个MediaFile实例共享相同的内部List<string>

You should not have a set accessor on this property at all, actually, nor should the MediaFile constructor be willing to take some external List<string> (unless it's going to copy it). 实际上,你根本不应该在这个属性上有一个set访问器, MediaFile构造函数也不应该愿意接受一些外部List<string> (除非它要复制它)。 Instead assign it only in the constructor for MediaFile to a new List<string>() ; 而是将它在MediaFile的构造函数中分配给new List<string>() ; this way you will ensure that each instance gets its own list: 这样,您将确保每个实例都有自己的列表:

public MediaFile()
{
    this.Tags = new List<string>();
}

Or: 要么:

public MediaFile(IEnumerable<string> tags)
{
    this.Tags = new List<string>(tags);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM