C#哈希表值会随着每个新键重置

C#哈希表值会随着每个新键重置,c#,collections,hashtable,C#,Collections,Hashtable,我有一个返回哈希表的函数。var dt从数据库中获取一组RevenueGroupId和ProductId,它们以1对多的结构映射在一起。例如: RevenueGroupID ProductID 1 312 1 313 1 315 2 317 2 319 3 401 3 410

我有一个返回哈希表的函数。var dt从数据库中获取一组RevenueGroupId和ProductId,它们以1对多的结构映射在一起。例如:

RevenueGroupID ProductID
1                 312
1                 313
1                 315
2                 317
2                 319
3                 401
3                 410
3                 411
3                 415
这两个数字的组合总是唯一的——没有重复。该函数构建一个键值对哈希表字典,其中键始终是RevenueGroupID,值是该RevenueGroupID的所有ProductId的列表。问题是:每次添加键值对时,所有以前的键值对都会被当前键值对覆盖。因此,在最后,所有键值对都与最后一个相同。我已经仔细检查了代码,并验证了每个键值对都是正确的和唯一的。我看不出重置的任何原因。我怀疑地查看了“productIDs.Clear();”,但我不明白为什么这会弄乱哈希表

public static Hashtable GetAllProductIDsInAllRevenueGroups()
{
    var productIDs = new List<int>();
    var ht = new Hashtable();

    string sql = @" {my sql here}";

    var dt = Utilities.GetDataTableForQuery(sql, null);

    int counter = 0;
    int revenueGroupID = 0;
    int lastRevenueGroupID = 0;

    foreach (DataRow row in dt.Rows)
    {
        revenueGroupID = Utilities.SafeInt(row["RevenueGroupID"]);
        int productID = Utilities.SafeInt(row["ProductID"]);

        if (revenueGroupID != lastRevenueGroupID && counter > 0)
        {
            ht.Add(lastRevenueGroupID, productIDs);
            productIDs.Clear();
        }

        productIDs.Add(productID);
        lastRevenueGroupID = revenueGroupID;
        counter++;
    }

    ht.Add(lastRevenueGroupID, productIDs);
    return ht;
}
public静态哈希表GetAllProductIDsInAllRevenueGroups()
{
var productIDs=新列表();
var ht=新哈希表();
字符串sql=@“{mySQL here}”;
var dt=Utilities.GetDataTableForQuery(sql,null);
int计数器=0;
int revenueGroupID=0;
int lastRevenueGroupID=0;
foreach(数据行中的数据行)
{
revenueGroupID=Utilities.SafeInt(第[“revenueGroupID”]);
int productID=Utilities.SafeInt(第[“productID”]行);
如果(revenueGroupID!=lastRevenueGroupID&&counter>0)
{
ht.Add(lastRevenueGroupID、productid);
productIDs.Clear();
}
productID.Add(productID);
lastRevenueGroupID=revenueGroupID;
计数器++;
}
ht.Add(lastRevenueGroupID、productid);
返回ht;
}

这是因为您一直在向哈希表中添加
productId
列表,而不进行复制,然后清除内容:

ht.Add(lastRevenueGroupID, productIDs);
productIDs.Clear(); // This removes all entries from the item stored at the lastRevenueGroupID key
这意味着同一个对象被一次又一次地添加,因此最终会得到包含最后一个条目内容的列表的多个副本

一个简单的解决方法是在将列表添加到哈希表之前创建一个新列表,如下所示:

ht.Add(lastRevenueGroupID, productIDs.ToList());
productIDs.Clear();

问题是您只使用一个列表,而不是为每个项目创建新列表。将列表添加到哈希表不会创建列表的副本,它只是添加引用。清除列表时,将清除哈希表中以前添加的所有项的列表,因为它们都是相同的列表

您可以创建一个新列表,并在启动新组时添加到哈希表中。在保留对列表的引用时,可以在列表被放入哈希表后继续向列表中添加数字:

public static Hashtable GetAllProductIDsInAllRevenueGroups()
{
    var productIDs;
    var ht = new Hashtable();

    string sql = @" {my sql here}";

    var dt = Utilities.GetDataTableForQuery(sql, null);

    int counter = 0;
    int revenueGroupID = 0;
    int lastRevenueGroupID = 0;

    foreach (DataRow row in dt.Rows)
    {
        revenueGroupID = Utilities.SafeInt(row["RevenueGroupID"]);
        int productID = Utilities.SafeInt(row["ProductID"]);

        if (counter == 0 || revenueGroupID != lastRevenueGroupID)
        {
            productIDs = new List<int>();
            ht.Add(revenueGroupID, productIDs);
        }

        productIDs.Add(productID);
        lastRevenueGroupID = revenueGroupID;
        counter++;
    }

    return ht;
}
public静态哈希表GetAllProductIDsInAllRevenueGroups()
{
var-productIDs;
var ht=新哈希表();
字符串sql=@“{mySQL here}”;
var dt=Utilities.GetDataTableForQuery(sql,null);
int计数器=0;
int revenueGroupID=0;
int lastRevenueGroupID=0;
foreach(数据行中的数据行)
{
revenueGroupID=Utilities.SafeInt(第[“revenueGroupID”]);
int productID=Utilities.SafeInt(第[“productID”]行);
如果(计数器==0 | | revenueGroupID!=lastRevenueGroupID)
{
productId=新列表();
ht.Add(revenueGroupID、ProductId);
}
productID.Add(productID);
lastRevenueGroupID=revenueGroupID;
计数器++;
}
返回ht;
}

注意:考虑使用严格类型的<代码>字典<代码>,而不是<代码>哈希表 .< /P> DasBrink:您的解决方案看起来很有前途,但没有编译。“'System.Collections.Generic.List'不包含'ToList'的定义”非常有用。谢谢,达斯!Guffa:我不知道该怎么做,因为在将ProductID添加到哈希表之前,您正在初始化它。它总是空的。@SweatCoder:当您将列表添加到哈希表中时,列表将为空,但随后您将数字添加到列表中。哈希表不包含列表的副本,它包含对列表的引用,因此它将与

productIDs
变量引用的列表相同。