You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Settings序列化器向带默认值的数组追加元素而非替换数组

问题:Settings.Default加载时列表元素被追加而非替换

加载Settings.Default时,自定义类型中的列表会出现反序列化元素追加到原有列表的问题,而非直接替换整个列表。

重现代码与配置

C#自定义设置类

class UserSettings
{
    public List<string> foos = new() { "foo", "bar" };
}

Settings.Settings 文件内容

<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="PhotoComparer.Properties" GeneratedClassName="Settings">
  <Profiles />
  <Settings>
    <Setting Name="UserSettings" Type="ProjectName.UserSettings" Scope="User">
      <Value Profile="(Default)" />
    </Setting>
  </Settings>
</SettingsFile>

App.Config 文件内容

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
    </configSections>
</configuration>

问题重现步骤

  1. 新建UserSettings实例,执行Settings.Default.Save()保存设置
  2. 关闭应用后重新启动,加载默认设置
  3. 此时Settings.Default.UserSettings.foos变为包含4个元素的列表:{"foo", "bar", "foo", "bar"}

问题原因

.NET的Settings系统在反序列化自定义类型时,会复用类中已初始化的实例(这里是字段初始化时创建的List<string>对象),而非创建新实例并替换原有属性/字段。反序列化过程会将数据追加到已存在的列表中,导致元素重复。

解决方案

方案1:延迟初始化列表,避免字段初始化时创建实例

通过构造函数或属性懒加载的方式初始化列表,确保反序列化时可以直接替换整个列表实例:

// 构造函数初始化
class UserSettings
{
    public List<string> foos;

    public UserSettings()
    {
        foos = new List<string> { "foo", "bar" };
    }
}

或使用属性懒加载:

class UserSettings
{
    private List<string> _foos;
    public List<string> foos
    {
        get => _foos ??= new List<string> { "foo", "bar" };
        set => _foos = value;
    }
}

方案2:实现ISerializable接口手动控制反序列化

通过实现ISerializable接口,在反序列化时直接创建新的列表实例替换原有对象:

using System.Runtime.Serialization;

class UserSettings : ISerializable
{
    public List<string> foos = new() { "foo", "bar" };

    // 无参构造函数必须保留
    public UserSettings() { }

    protected UserSettings(SerializationInfo info, StreamingContext context)
    {
        // 反序列化时直接获取新列表,若为null则使用默认值
        foos = (List<string>)info.GetValue("foos", typeof(List<string>)) ?? new List<string> { "foo", "bar" };
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("foos", foos);
    }
}

内容的提问来源于stack exchange,提问作者Doshorte Dovencio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 12:15:31