我使用一个列表来包含从XML文件解析的数据,使用字符串作为其成员:
public class ServerList
{
public string ServerName { set; get; }
public string ServerReboot { set; get; }
public string ServerShutdown { set; get; }
public ServerList()
{
ServerName = "";
ServerReboot = "";
ServerShutdown = "";
}
}
从主窗体中我启动一个编辑器表单并将列表传递给它。在此编辑器表单上,用户可以在列表中添加或删除条目条目,以及对列表的某些部分进行更改。如果他们单击“确定”按钮,我希望能够将编辑器表单中的列表拉回到主窗体中,但如果他们单击“取消”,我希望删除这些更改。这是编辑器表单的提取方式:
private void mnuEdit_Click(object sender, EventArgs e)
{
frmEditor theEditor = new frmEditor();
theEditor.updatedServerList = theServerList;
DialogResult res = theEditor.ShowDialog();
if (res == DialogResult.OK)
{
theServerList = theEditor.updatedServerList.ToList();
SetupFilters(GroupOrBatch.Group);
// other processing to update the main form from the updated list
}
}
在编辑表格中,这是如何收到的:
public partial class frmEditor : Form
{
private List<ServerList> myServerList = new List<ServerList>();
public List<ServerList> updatedServerList
{
get { return myServerList; }
set { myServerList = value.ToList(); }
}
....
我发现,虽然列表结构似乎被复制到新变量,但实际数据仍然链接到原始列表。即使用户单击“取消”,并且修改后的列表未复制回原件,原件也已更改。
这给我留下了两个选项之一 - 或者我可以找到一些方法来对列表进行全深度克隆(可以在取消时删除),或者我完全删除取消按钮并且所有编辑都是实时的。
答案 0 :(得分:1)
class
通过引用存储在列表中。 .ToList()
仅使用指向那些ServerList
的相同引用创建列表的浅表副本。因此,通过对卷影副本进行任何更改,原始列表仍会受到影响。
您需要对列表进行深层复制,并传递它们以进行编辑:
<强> SERVERLIST ::克隆强>
public class ServerList
{
// properties...
// ctor...
public ServerList Clone()
{
return new ServerList
{
ServerName = ServerName,
ServerReboot = ServerReboot,
ServerShutdown = ServerShutdown,
});
}
}
<强> mnuEdit_Click 强>
private void mnuEdit_Click(object sender, EventArgs e)
{
frmEditor theEditor = new frmEditor();
theEditor.updatedServerList = theServerList.Select(x => x.Clone()).ToList(); /*changed */
DialogResult res = theEditor.ShowDialog();
if (res == DialogResult.OK)
{
theServerList = theEditor.updatedServerList; /* changed */
SetupFilters(GroupOrBatch.Group);
// other processing to update the main form from the updated list
}
}
注意:.ToList()
上的updatedServerList.get
不是必需的。
答案 1 :(得分:0)
作为替代方案,由于您的数据集非常小,请将数据转换为结构:
public struct ServerList
{
public string ServerName { get; private set; }
public string ServerReboot { get; private set; }
public string ServerShutdown { get; private set; }
public ServerList(string name, string reboot, string shutDown)
{
this.ServerName = name;
this.ServerReboot = reboot;
this.ServerShutdown = shutDown;
}
}
struct
是值类型(与引用类型相对),值语义将应用于它。请考虑以下事项:
var listA = new ServerList("Foo", "Daily", "Never");
var listB = listA;
listA
及其所有值的副本存储在listB
中,而不是参考。对于字符串,引用了副本,但字符串无论如何都是不可变的,因此没有问题。
CON:结构应该是不可变的。初始化它们后,您无法更改其数据。在采用此解决方案之前考虑一下。