在我的代码中,我有一个维护许多列表的类。我们暂时关注其中一个,因为它突出了问题。
internal List<Badge> Badges { get; private set; }
在代码中,我在解析XML文档时将Badge
个实例添加到此列表中。稍后,我想更新列表中的各个实例,以便将数据写回XML。由于数据的XML结构与原始文件结构的不同,所以涉及到一些hocus-pocus,但这很大程度上是映射出来的。当我尝试更新List<Badge>
中的项目时,出现了惊喜。
具体来说,有问题的代码在这里:
// Get the current badge from the loaded XML data, so we can update it.
var currentBadge = this.GameData.GetCurrentBadge();
我总是得到有效的徽章。正如我已经发现的那样,令人惊讶的是,这个简单的测试总是失败:
var result = this.GameData.Badges.IndexOf(currentBadge);
result
始终求值为-1,表示该对象在集合中不存在。 (编辑:更新currentBadge
上的属性对this.GameData.Badges
中匹配项的内容没有任何影响。)这使我得出结论我正在获取我的对象的副本,而不是参考,正如我所期望的那样。
对于好奇的人来说,从GameData类中检索徽章的代码包含在下面。我有一种潜在的怀疑,这是通用列表的记录行为,这是我第一次偶然发现它。如果是这样的话,那我就是一个非常粗鲁的觉醒。如果不是,我真的很想知道为什么我的物品会从原件中“断开”。
private Badge GetCurrentBadge()
{
var badgeItem = GetCurrentBadgeItem();
if (badgeItem != null)
{
return this.GameData.GetBadgeByText(badgeItem.Text);
}
return null;
}
private MenuOption GetCurrentBadgeItem()
{
if (!(this.currentItem is MenuOption &&
(this.currentItem as MenuOption).IsLocked))
{
return null;
}
MenuOption result = null;
var children = this.currentMenu.Children;
for (var n = children.Count - 1; n >= 0; n--)
{
var child = children[n] as MenuOption;
if (child == null || !child.IsLocked)
{
break;
}
if (!child.Text.StartsWith(" "))
{
result = child;
break;
}
}
return result;
}
更新:每个请求,GetBadgeByText,来自GameData类。
internal Badge GetBadgeByText(string badgeText)
{
foreach (var badge in Badges)
{
if (badge.Text.ToLower() == badgeText.ToLower())
{
return badge;
}
}
return null;
// var b = (from l in Badges
// where l.Text.ToLower().StartsWith(badgeText.ToLower())
// select l).FirstOrDefault();
//return b;
}
正如你所看到的,无论是否有Linq,我都试过它,只是为了消除它作为罪魁祸首。改变实施没有明显的效果。
对于记录,此应用程序中的所有对象都是CLASSES。没有任何结构。
更新#2:徽章课程。
internal class Badge
: GameDataItem
{
public Badge()
: base()
{
}
public string AuthId { get; set; }
public string Category { get; set; }
public string Description { get; set; }
public bool IsAccoladePower { get; set; }
public string RequiredBadges { get; set; }
public override string ToString()
{
return Text;
}
internal string ToXml()
{
var template = "<Badge value=\"{0}\" title=\"{1}\" category=\"{2}\" authid=\"{3}\" requires=\"{4}\" accolade=\"{5}\" description=\"{6}\" />";
return string.Format(template,
this.Value,
this.Text,
this.Category,
this.AuthId,
this.RequiredBadges,
this.IsAccoladePower,
this.Description);
}
}
以防万一有人要求它,基类:
internal class GameDataItem
{
private string _text;
public string Text
{
get
{
return this._text;
}
set
{
this._text = value.Replace("<", "<")
.Replace(">", ">")
.Replace("&", "&");
}
}
public string Value { get; set; }
public override string ToString()
{
return Text + "=\"" + Value + "\"";
}
}
答案 0 :(得分:1)
或者:
List<T>
不会克隆对象或做任何其他类型的欺骗。)Badge
是一个结构,而不是一个类,这意味着你实际上并没有对它进行引用,因为它是一个值类型。答案 1 :(得分:1)
在我看来,这与MenuOption
Equals(object)
的实施有关。在决定要返回的内容时,IndexOf()
的{{1}}方法将使用List<>
。
答案 2 :(得分:0)
通用列表&lt; T&gt;不复制对象。你添加对它的引用,并出现相同的引用 - 所以代码中必定存在另一个问题。
如何实施GetBadgeFromText?它是直接从Badges
列表中读取的吗?
这是一个网络应用程序吗?如果是,您的列表是否存在于请求之间,或者是否在每个请求中反序列化和序列化(这也可能是问题)。