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

LeetCode句子相似性题:字典键莫名消失问题排查

问题排查:Dictionary无显式修改却为空导致KeyNotFoundException

问题现象

编写LeetCode「sentence-similarity」题解时,出现异常:构建完成的Dictionary首次打印可正常显示键值对,但后续循环中无法找到已存在的键(如great),抛出System.Collections.Generic.KeyNotFoundException,且此时字典的键集合为空。

相关代码

public class Solution {
public bool AreSentencesSimilar(string[] sentence1, string[] sentence2, IList<IList<string>> similarPairs) {
    // TODO: Validation

    int n = sentence1.Length;
    if (sentence2.Length != n)
        return false;

    IDictionary<string, ICollection<string>> synonyms = BuildSynonymLookup(similarPairs);
    // ------------------ TEST! ---------------------
    foreach (var kvp in synonyms)
        Console.WriteLine("{0} -> [{1}]", kvp.Key, string.Join(", ", kvp.Value));
    /*
        The above prints

        great -> [fine, great]
        fine -> [great, fine]
        drama -> [acting, drama]
        acting -> [drama, acting]
        skills -> [talent, skills]
        talent -> [skills, talent]
    */
    // -------------------------------------------------
    for (int i = 0; i < n; ++i)
    {
        string word1 = sentence1[i], word2 = sentence2[i];
        // --------------------- TEST! ---------------------------
        if (!synonyms.ContainsKey(word1))
        {
            Console.WriteLine("synonyms does not contain '{0}'. It contains [{1}]", word1, string.Join(",", synonyms.Keys));
        }
        // ---- The above prints 'synonyms does not contain great. It contains []'
        if (!synonyms[word1].Contains(word2)) // Unhandled exception. System.Collections.Generic.KeyNotFoundException: The given key 'great' was not present in the dictionary.
            return false;
    }
    return true;
}

private static IDictionary<string, ICollection<string>> BuildSynonymLookup(in IList<IList<string>> similarPairs)
{
    var synonyms = new Dictionary<string, ICollection<string>>(similarPairs.Count);
    foreach (var pair in similarPairs)
    {
        string w0 = pair[0], w1 = pair[1];
        AddSynonym(synonyms, w0, w1);
        AddSynonym(synonyms, w0, w0);            
        AddSynonym(synonyms, w1, w0);  
        AddSynonym(synonyms, w1, w1);                  
    }
    return synonyms;
}

private static void AddSynonym(in IDictionary<string, ICollection<string>> synonyms, in string word0, in string word1)
{
    if (!synonyms.TryGetValue(word0, out ICollection<string> S))
        synonyms[word0] = S = new HashSet<string>(4);
    S.Add(word1);     
}
}

问题原因

问题出在**in关键字的误用**:

  • in关键字用于传递只读引用参数,设计目的是避免值类型的复制开销,同时保证参数不会被重新赋值。
  • 但对于Dictionary这类可变引用类型,虽然in允许修改对象内部状态,但编译器在处理接口类型的in参数时,可能会触发异常的优化行为,导致后续访问时字典的引用失效或内部状态被异常重置。
  • 你在BuildSynonymLookup和AddSynonym方法的参数上都添加了in修饰符,这完全是多余的——你需要修改字典的内容,in的只读约束不仅没用,反而引发了异常行为。

解决方案

移除所有不必要的in关键字,修改后的方法签名如下:

private static IDictionary<string, ICollection<string>> BuildSynonymLookup(IList<IList<string>> similarPairs)
// 移除参数前的in

private static void AddSynonym(IDictionary<string, ICollection<string>> synonyms, string word0, string word1)
// 移除所有参数前的in

移除后,字典的引用和内部状态将保持稳定,后续循环中可以正常访问已存在的键。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 05:08:15