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

C# foreach遍历KeyValuePair时如何读取struct内容写入txt文件

问题根因

直接将结构体对象传入WriteLine格式化参数时,默认调用object.ToString()方法,未重写ToString()的值类型会直接返回类型全名称,也就是你看到的结构体名称,无法输出实际字段/属性值。
另外你现有代码存在逻辑错误:在内层循环第一次执行时就调用了tw2.Close(),后续循环写入时会触发流已释放的异常。

基础写入功能修复

通过递归解析方法处理任意类型的输入值,对结构体/自定义类型通过反射读取公开实例的属性和字段内容,同时修正流释放的逻辑,代码如下:

private void show2(Dictionary<string, object> state)
{
    // using语句会在执行完毕后自动释放流资源,无需手动调用Close
    using TextWriter tw2 = new StreamWriter(savepath2);
    foreach (KeyValuePair<string, object> group1 in state)
    {
        // 增加类型判断,避免值不符合预期时强转报错
        if (group1.Value is not Dictionary<string, object> group2)
        {
            tw2.WriteLine($"Id: {group1.Key} -- 非字典类型值: {ParseObjectValue(group1.Value)}");
            continue;
        }
        foreach (KeyValuePair<string, object> innerKey in group2)
        {
            tw2.WriteLine("Id: {0} -- Type: {1} -- Value: {2}", 
                group1.Key, innerKey.Key, ParseObjectValue(innerKey.Value));
        }
    }
}

/// <summary>
/// 递归解析任意对象为可读字符串
/// </summary>
private string ParseObjectValue(object obj)
{
    if (obj == null) return "null";
    Type objType = obj.GetType();
    // 基础值类型、字符串直接返回ToString结果
    if (obj is string || objType.IsPrimitive || obj is decimal || obj is DateTime)
    {
        return obj.ToString();
    }
    // 嵌套字典递归解析
    if (obj is Dictionary<string, object> dict)
    {
        var dictContent = dict.Select(kv => $"{kv.Key}:{ParseObjectValue(kv.Value)}");
        return $"{{{string.Join(", ", dictContent)}}}";
    }
    // 结构体、自定义类通过反射读取所有公开实例属性、字段
    if (objType.IsValueType || objType.IsClass)
    {
        List<string> memberValues = new List<string>();
        // 读取公开属性,跳过索引器
        foreach (var prop in objType.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
        {
            if (prop.GetIndexParameters().Length > 0) continue;
            object val = prop.GetValue(obj);
            memberValues.Add($"{prop.Name}={ParseObjectValue(val)}");
        }
        // 读取公开字段
        foreach (var field in objType.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
        {
            object val = field.GetValue(obj);
            memberValues.Add($"{field.Name}={ParseObjectValue(val)}");
        }
        return $"{objType.Name}:{{{string.Join(", ", memberValues)}}}";
    }
    return obj.ToString();
}
纯文本可读序列化方案

BinaryFormatter已经被官方标记为不安全类型,不推荐继续使用。如果需要直接生成可直接打开查看的文本格式存储嵌套结构,优先使用JSON序列化,输出为带缩进的格式化纯文本,天然支持嵌套字典、结构体等所有常规类型,流写入实现简单:

// .NET Core 3.0+/.NET 5+ 自带System.Text.Json,.NET Framework可通过NuGet安装对应包
private void SaveFile(object state)
{
    using var stream = File.Open(savepath, FileMode.Create);
    using var writer = new StreamWriter(stream);
    string jsonContent = System.Text.Json.JsonSerializer.Serialize(state, new JsonSerializerOptions()
    {
        WriteIndented = true, // 开启缩进排版,生成的文件结构清晰可读
        Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping // 避免中文等非ASCII字符被转义
    });
    writer.Write(jsonContent);
}
  • 如果需要输出结构体的非公开成员,修改反射逻辑的BindingFlags参数,加上NonPublic枚举即可
  • JSON序列化方案兼容性更强,可通过配置MaxDepth参数限制递归深度,避免循环引用导致的栈溢出
  • 禁止在循环内释放写入流,否则会导致后续写入操作失败

内容的提问来源于stack exchange,提问作者hesam gol

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 08:45:32