c# - 为什么我的列表中的成员会被所述列表的最后一个成员覆盖?

标签 c# list c#-4.0 nested-lists

我正在尝试编写一个程序,打印出(在字符串变量中)有关 mdb 数据库的以下信息:

表名
表格的总列数

列列表如下:

栏目名称:
列数据类型:

为此,我使用了两种自定义类型(公共(public)类),当然还有列表。这是我到目前为止的代码(顺便说一下,由于这里收集的问题和答案,它已经进行了不小的调整):

以下是我创建的用于定义我正在使用的两种新类型的类:

public class ClmnInfo
{
    public string strColumnName { get; set; }
    public string strColumnType { get; set; }
}

public class TblInfo
{
    public string strTableName { get; set; }
    public int intColumnsQty { get; set; }
    public List<ClmnInfo> ColumnList { get; set; }

}

这是实际获取数据的代码。请记住,我使用 OleDB 连接到实际数据并且一切正常,除了我将在下面描述的问题。
作为示例,我目前正在使用一个简单的 1 个表 db 测试此代码,其中包含 12 个字符串类型的列,保存为 1 个 int32(Access 中的 Long Int)。
//Here I declare and Initialize all relevant variables and Lists
TblInfo CurrentTableInfo = new TblInfo();
ClmnInfo CurrentColumnInfo = new ClmnInfo();
List<TblInfo> AllTablesInfo = new List<TblInfo>();

 //This loop iterates through each table obtained and imported previously in the program
int i = 0;
foreach (DataTable dt in dtImportedTables.Tables)
{


    CurrentTableInfo.strTableName = Globals.tblSchemaTable.Rows[i][2].ToString(); //Gets the name of the current table
    CurrentTableInfo.intColumnsQty = dt.Columns.Count; //Gets the total number of columns in the current table
    CurrentTableInfo.ColumnList = new List<ClmnInfo>(); //Initializes the list which will house all of the columns 

    //This loop iterates through each column in the current table
    foreach (DataColumn dc in dt.Columns)
    {
        CurrentColumnInfo.ColumnName = dc.ColumnName;  // Gets the current column name
        CurrentColumnInfo.ColumnType = dc.DataType.Name; // Gets the current column data type

        CurrentTableInfo.ColumnList.Add(CurrentColumnInfo); // adds the information just obtained as a member of the columns list contained in CurrentColumnInfo 
     }
//BAD INSTRUCTION FOLLOWS:

        AllTablesInfo.Add(CurrentTableInfo); //This SHOULD add The collection of column_names and column_types in a "master" list containing the table name, the number of columns, and the list of columns
    }

我调试了代码并观察了所有变量。它工作得很好(表名和列数量被正确注册,以及该表的 column_names、column_types 列表),但是当“坏”指令被执行时,AllTablesInfo 的内容根本不是它们应该是的.
表名是正确的,列数也是正确的,列列表甚至应该有 12 个成员,但是列表的每个成员都是相同的,即我正在检查的数据库的 LAST 列。谁能向我解释为什么 CurrentTableInfo 在添加到 AllTablesInfo 列表时会以这种方式被覆盖?

最佳答案

您正在创建一个 TblInfo对象,然后在每次迭代中更改属性。您的列表包含对同一对象的大量引用。只需移动这一行:

TblInfo CurrentTableInfo = new TblInfo();

到第一个循环的内部,这一行:
ClmnInfo CurrentColumnInfo = new ClmnInfo();

在嵌套 foreach 内循环,以便您在每次迭代中创建新实例。

下一个:
  • 重要
    确保您了解它之前失败的原因。阅读我关于 references 的文章如果你不确定对象和引用(以及值类型)在 C# 中是如何工作的
  • 使用camelCased名称而不是 CamelCased用于局部变量的
  • 考虑为 ClmnInfo 使用对象初始化器
  • 更改您的类型名称以避免不必要的缩写(TableInfoColumnInfo)
  • 更改您的属性名称以避免伪匈牙利符号,并将它们设为 PascalCased
  • 考虑将整个事情重写为 LINQ 查询(相对高级)

  • LINQ 之前的更改将使您的代码看起来像这样:
    List<TableInfo> tables = new List<TableInfo>();
    
    int i = 0;
    foreach (DataTable dt in dtImportedTables.Tables)
    {
        TableInfo table = new TableInfo
        {
            Name = Globals.tblSchemaTable.Rows[i][2].ToString(),
            // Do you really need this? Won't it be the same as Columns.Count?
            ColumnCount = dt.Columns.Count,
            Columns = new List<ColumnInfo>()
        };
    
        foreach (DataColumn dc in dt.Columns)
        {
            table.Columns.Add(new ColumnInfo {
                                Name = dc.ColumnName,
                                Type = dc.DataType.Name
                              });
        }
        tables.Add(table); 
        // I assume you meant to include this?
        i++;
    }
    

    使用 LINQ:
    List<TableInfo> tables = 
        dtImportedTables.Tables.Zip(Globals.tblSchemaTable.Rows.AsEnumerable(),
            (table, schemaRow) => new TableInfo {
                Name = schemaRow[2].ToString(),
                // Again, only if you really need it
                ColumnCount = table.Columns.Count,
                Columns = table.Columns.Select(column => new ColumnInfo {
                            Name = column.ColumnName,
                            Type = column.DataType.Name
                          }).ToList()
            }
        }).ToList();
    

    关于c# - 为什么我的列表中的成员会被所述列表的最后一个成员覆盖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16971538/

    相关文章:

    c# - 如何使用 C# 使用 Protobuf 进行非阻塞套接字读取?

    python - 将指标函数应用于列表

    c# - 如何更快/更智能地读取文本文件?

    c# - 在 windows 启动时设置 c# windows 应用程序

    c# - Android Xamarin 从 Android.Net.Uri 获取绝对路径

    c# - MVVM和序列化-如何访问类的实例? [复制]

    c# - ASP.Net 快速按钮单击在 UpdatePanel 中添加控件会产生并发问题

    python - 对嵌套列表进行排序 : Exclude first item from sorting

    list - Prolog列表问题

    c# - 计算对数底数 2