List<T> 将 foreach 循环中的所有项目覆盖为最后一个值

Posted

技术标签:

【中文标题】List<T> 将 foreach 循环中的所有项目覆盖为最后一个值【英文标题】:List<T> overwrites all the items inside a foreach loop to the last value 【发布时间】:2015-07-04 17:00:13 【问题描述】:

我正在尝试构建一个 Windows 应用程序,其中有一个组合框,并且在 Load() 期间,我用我的 app.Config 文件中可用的所有连接字符串填充这个组合框。

这里是app.Config sn-p:

<!-- Adding Multiple Servers in Connection String-->
<connectionStrings>
   <add name="SQLConnect-1"
         connectionString="Data Source=SAHIL; Initial Catalog=RecordComparisonTool; Integrated Security=SSPI"
         providerName="System.Data.SqlCLient"/>

   <add name="SQLConnect-2"
     connectionString="Data Source=SAHIL; Initial Catalog=RecordComparisonTool; User Id=test; Password=12123; Integrated Security=SSPI"
     providerName="System.Data.SqlCLient"/>

   <add name="SQLConnect-3"
     connectionString="Data Source=SAHIL; Initial Catalog=RecordComparisonTool; User Id=test; Password=32315;  Integrated Security=True"
     providerName="System.Data.SqlCLient"/>
 </connectionStrings>

我创建了一个 CompareResult 类,我在其中尝试从 app.Config 中获取所有值并将其显示到组合框。

namespace RecordComparisonTool_Win

   public class ConnectionString
   
        public string name  get; set; 
        public string conString  get; set; 
        public string provider  get; set; 
    

    public class CompareResult
    

        public List<ConnectionString> GetConnection()
        
            List<ConnectionString> conStr = new List<ConnectionString>();
            ConnectionString conn = new ConnectionString();

            foreach (ConnectionStringSettings css in ConfigurationManager.ConnectionStrings)
            
                if (!(css.Name == "LocalSqlServer" || css.Name == "LocalmysqlServer"))
                
                    conn.name = css.Name;
                    conn.conString = css.ConnectionString;
                    conn.provider = css.ProviderName;

                    conStr.Add(conn);
                
            
            return conStr;
        

    

问题是当我尝试将它与组合框绑定时,它根据 app.Config 文件显示三个记录,但所有记录的值都与“SQLConnect-3”相同。对于所有记录,我无法找到使用“SQLConnect-3”更新列表的原因。请帮助修复错误。这是我将此列表绑定到 ComboBox 的 sn-p

protected void LoadConnection()

    CompareResult compareResult = new CompareResult();

    List<ConnectionString> connectionString = new List<ConnectionString>();
    connectionString = compareResult.GetConnection();

    cbTokenLeft.DataSource = connectionString;

    cbTokenLeft.DisplayMember = "name";
    cbTokenLeft.ValueMember = "conString";


【问题讨论】:

更新:根据下面提到的答案,我在 foreach() 循环之外实例化 ConnectionString 的对象时犯了一个错误,并且每次都会覆盖数据。通过在 foreach() 循环中实例化它,问题得到了解决。谢谢大家的解决方案。 【参考方案1】:

这个:

conn.name = css.Name;
conn.conString = css.ConnectionString;
conn.provider = css.ProviderName;

conStr.Add(conn);

每次迭代都会覆盖您的 ConnectionString 引用。您需要在每个循环中分配一个新的ConnectionString

foreach (ConnectionStringSettings css in ConfigurationManager.ConnectionStrings)

    if (!(css.Name == "LocalSqlServer" || css.Name == "LocalMySqlServer"))
    
        var conn = new ConnectionString
        
           name = css.Name;
           conString = css.ConnectionString;
           provider = css.ProviderName;
        
        conStr.Add(conn);
    

【讨论】:

【参考方案2】:

ConnectionString conn = new ConnectionString(); 行移到最里面的循环内。它是一个参考类,您一遍又一遍地将同一个实例添加到您的列表中。

    public List<ConnectionString> GetConnection()
    
        List<ConnectionString> conStr = new List<ConnectionString>();

        foreach (ConnectionStringSettings css in ConfigurationManager.ConnectionStrings)
        
            if (!(css.Name == "LocalSqlServer" || css.Name == "LocalMySqlServer"))
            
                ConnectionString conn = new ConnectionString();
                conn.name = css.Name;
                conn.conString = css.ConnectionString;
                conn.provider = css.ProviderName;

                conStr.Add(conn);
            
        
        return conStr;
    

【讨论】:

【参考方案3】:

由于您要在循环之外实例化 ConnectionString,因此所有迭代都使用(并覆盖)相同的实例。您需要在循环中中实例化它,以便每次迭代都会获得一个新实例:

foreach (ConnectionStringSettings css in ConfigurationManager.ConnectionStrings)

    if (!(css.Name == "LocalSqlServer" || css.Name == "LocalMySqlServer"))
    
        ConnectionString conn = new ConnectionString();

        conn.name = css.Name;
        conn.conString = css.ConnectionString;
        conn.provider = css.ProviderName;

        conStr.Add(conn);
    

您也可以使用 LINQ 表达相同的代码:

var conStr = 
(
    from css in ConfigurationManager.ConnectionStrings
    where !(css.Name == "LocalSqlServer" || css.Name == "LocalMySqlServer")
    select new ConnectionString
    
        name = css.Name,
        conString = css.ConnectionString,
        provider = css.ProviderName,
    
).ToList();

【讨论】:

以上是关于List<T> 将 foreach 循环中的所有项目覆盖为最后一个值的主要内容,如果未能解决你的问题,请参考以下文章

List<T>.ForEach 带索引

C#中如何用for循环遍历List<类>?

将list转换为datatable的方法

C#中list<>定义的变量,我用foreach()循环查找 与 list<> .find 查找两个哪个效率高?后者是不是用了算法

ArrayList,Hashtable,List<T>,Dictionary<K,V>

foreach