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

如何从DataGridView加载List<T>?加载列数据遇空引用异常求解

解决DataGridView加载List时的NullReferenceException问题

先分析你遇到的空引用异常,大概率出自这几个场景:

  • 目标单元格的Value是null或者DBNull.Value,直接强制(string)转换会触发异常
  • 遍历到了DataGridView默认的新增空白行(Rows[i].IsNewRow为true),这一行的单元格值全为空
  • 列索引Cells[2]超出了实际列数,导致单元格对象本身就是null

给你修复后的LoadStringList方法,补上了空值校验和跳过新增行的逻辑:

public static List<string> LoadStringList() { 
    List<string> stringList = new List<string>(); 
    // 先确保DataGridView实例不为空
    if (contactDataGridView == null || contactDataGridView.RowCount == 0) {
        return stringList;
    }
    // 遍历行时跳过新增空白行
    foreach (DataGridViewRow row in contactDataGridView.Rows) {
        if (row.IsNewRow) continue;
        
        // 检查目标单元格是否存在
        if (row.Cells.Count > 2 && row.Cells[2] != null) {
            // 统一处理DBNull和null的情况,转成空字符串或按需忽略
            string cellValue = row.Cells[2].Value == DBNull.Value 
                ? string.Empty 
                : row.Cells[2].Value?.ToString();
            
            // 可选:只添加非空非空白的内容
            if (!string.IsNullOrWhiteSpace(cellValue)) {
                stringList.Add(cellValue);
            }
        }
    }
    return stringList; 
}

从DataGridView加载List的通用方法

下面提供两种实用的通用加载思路,适配不同场景:

1. 强类型实体手动映射(性能优、易维护)

如果你的目标是已知结构的实体类,比如Contact,可以手动绑定单元格值到实体属性:

// 示例实体类
public class Contact {
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}

public static List<Contact> LoadContactList() {
    List<Contact> contacts = new List<Contact>();
    if (contactDataGridView == null || contactDataGridView.RowCount == 0) {
        return contacts;
    }
    
    foreach (DataGridViewRow row in contactDataGridView.Rows) {
        if (row.IsNewRow) continue;
        
        Contact contact = new Contact();
        // 按列索引/列名赋值,同时处理空值和类型转换
        contact.Name = row.Cells["ColumnName_Name"].Value?.ToString() ?? string.Empty;
        contact.Age = int.TryParse(row.Cells["ColumnName_Age"].Value?.ToString(), out int age) ? age : 0;
        contact.Email = row.Cells[2].Value?.ToString() ?? string.Empty;
        
        contacts.Add(contact);
    }
    return contacts;
}

// 使用方式
List<Contact> contactList = LoadContactList();

2. 反射自动映射(灵活适配任意实体)

如果想适配任意实体类,不需要手动写映射逻辑,可以用反射根据列名和属性名自动匹配:

public static List<T> LoadGenericEntityList<T>(DataGridView dgv) where T : new() {
    List<T> entityList = new List<T>();
    if (dgv == null || dgv.RowCount == 0) return entityList;
    
    Type entityType = typeof(T);
    var properties = entityType.GetProperties();
    
    foreach (DataGridViewRow row in dgv.Rows) {
        if (row.IsNewRow) continue;
        
        T entity = new T();
        foreach (var prop in properties) {
            // 找到与属性名匹配的列(忽略大小写)
            DataGridViewColumn targetCol = dgv.Columns.Cast<DataGridViewColumn>()
                .FirstOrDefault(col => string.Equals(col.Name, prop.Name, StringComparison.OrdinalIgnoreCase));
            
            if (targetCol != null && row.Cells[targetCol.Index] != null) {
                object cellValue = row.Cells[targetCol.Index].Value;
                // 把DBNull转成null,统一处理空值
                if (cellValue == DBNull.Value) cellValue = null;
                
                // 尝试转换类型并赋值,转换失败时设为默认值
                try {
                    object convertedValue = cellValue == null 
                        ? prop.PropertyType.IsValueType ? Activator.CreateInstance(prop.PropertyType) : null
                        : Convert.ChangeType(cellValue, prop.PropertyType);
                    prop.SetValue(entity, convertedValue);
                } catch {
                    // 可选:记录转换失败日志
                    prop.SetValue(entity, null);
                }
            }
        }
        entityList.Add(entity);
    }
    return entityList;
}

// 使用方式
List<Contact> contactList = LoadGenericEntityList<Contact>(contactDataGridView);

额外注意事项

  • 始终优先检查DataGridView、DataGridViewRow、DataGridViewCell是否为null,从根源避免空引用
  • 数据库空值在DataGridView中会以DBNull.Value存在,不能直接转换为普通.NET类型,必须单独处理
  • 记得跳过IsNewRow:默认情况下DataGridView最后一行是用于新增的空白行,不需要加入结果列表

内容的提问来源于stack exchange,提问作者Andrey Kaplun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:30:00