C#中DataGridView操作触发数组索引越界问题求助
DataGridView数组索引越界问题分析与修复
问题场景
你需要给DataGridView的每一行询问测量样本数量,生成对应最大数量的列,并将每行超过自身样本数的列标红,但运行时出现数组索引越界错误。
原代码
nombredemesures = new int[] { }; foreach (DataGridViewRow row in dataGridView2.Rows) { if (row.Cells[$"{comboBox1.Text + comboBox2.Text}DataGridViewTextBoxColumn"].Value?.ToString() is "") { row.Visible = false; } else { string result = Interaction.InputBox($"Valeur de :{row.Cells[\"ItemDataGridViewTextBoxColumn\"].Value?.ToString()}", "Title", "Default Text"); nombredemesures = nombredemesures.Concat(new int[] { int.Parse(result) }).ToArray(); } } int max = 0; foreach (int value in nombredemesures) { if (value > max) max = value; } int k = 0; for (int i = 1; i <= max; i++) { dataGridView2.Columns.Add($"Test{i}", $"Donée de mesure{i}"); } var resultt = from DataGridViewRow roww in dataGridView2.Rows select roww.Index; foreach (var i in resultt) { for (int j = max;j>(nombredemesures[k]); j--) { dataGridView2.Rows[i].Cells[$"Test{j}"].Style.BackColor = System.Drawing.Color.Red; } k++; }
错误原因
数组越界的核心问题是数据不匹配:
- 你仅在行可见且单元格非空时,才往
nombredemesures数组中添加元素,但后续遍历的是DataGridView的所有行(包括被设置为Visible=false的行)。 - 假设总行数为4,其中1行被隐藏,那么
nombredemesures的长度是3,但遍历会执行4次,当k=3时,访问nombredemesures[3]就会触发索引越界。
此外还有两个次要问题:
- 使用数组
Concat的方式性能极差,每次添加元素都会创建新数组,建议改用List<T>。 int.Parse未做输入验证,用户输入非数字时会直接抛出异常。
修复后的代码
改用列表存储行与样本数的关联,避免索引不匹配的问题,同时增加输入验证:
// 用列表存储可见行和对应的样本数,避免索引不匹配 var rowMeasurements = new List<(DataGridViewRow Row, int MeasurementCount)>(); foreach (DataGridViewRow row in dataGridView2.Rows) { string cellValue = row.Cells[$"{comboBox1.Text + comboBox2.Text}DataGridViewTextBoxColumn"].Value?.ToString(); if (string.IsNullOrEmpty(cellValue)) { row.Visible = false; } else { string input = Interaction.InputBox($"Valeur de :{row.Cells["ItemDataGridViewTextBoxColumn"].Value?.ToString()}", "Title", "Default Text"); // 验证输入是否为有效数字,避免异常 if (int.TryParse(input, out int count)) { rowMeasurements.Add((row, count)); } else { // 输入无效时设置默认值,可根据需求调整 rowMeasurements.Add((row, 0)); } } } // 没有需要处理的行时直接返回 if (rowMeasurements.Count == 0) return; // 简化最大值计算 int maxCount = rowMeasurements.Max(item => item.MeasurementCount); // 添加测量列 for (int i = 1; i <= maxCount; i++) { dataGridView2.Columns.Add($"Test{i}", $"Donée de mesure{i}"); } // 遍历关联数据,设置列背景色 foreach (var item in rowMeasurements) { DataGridViewRow row = item.Row; int count = item.MeasurementCount; for (int j = maxCount; j > count; j--) { // 额外检查列是否存在,避免列名拼写错误导致的问题 if (dataGridView2.Columns[$"Test{j}"] != null) { row.Cells[$"Test{j}"].Style.BackColor = System.Drawing.Color.Red; } } }
关键改进点
- 使用
List<(DataGridViewRow Row, int MeasurementCount)>存储可见行和样本数的关联,确保后续遍历的行都有对应的样本数,不会出现索引越界。 - 用
int.TryParse替代int.Parse,避免输入非数字时抛出异常。 - 简化最大值计算,使用LINQ的
Max方法更简洁。 - 增加列存在性检查,避免列名拼写错误导致的额外问题。
内容的提问来源于stack exchange,提问作者LiterallyGutsFromBerserk
相关产品推荐
相关产品推荐

