C#英波双向翻译字典触发KeyNotFoundException错误的问题求助
问题排查与解决方案
为什么会抛出KeyNotFoundException?
核心问题出在字典的映射方向和你的反向校验逻辑不匹配:
- 你创建的
Dictionary<string, string>是**波兰语(Key)→英语(Value)**的映射,所有Key都是波兰语单词。 - 当你做波兰语到英语的反向校验时,应该是输入英语单词(假设
textBox1里是英语),然后要验证textBox2的波兰语是否正确。但你还是用了myDict[textBox1.Text]——这相当于拿英语单词当Key去字典里找,而字典里根本没有英语Key,自然会触发找不到Key的错误。
另外还有个小问题:rnd.Next(1,15)生成的是1到14的整数,但字典的Keys/Values集合索引是从0开始的,这会导致你永远取不到第一个元素("Pies"/"Dog"),而且硬编码数字也不够灵活,最好用字典的Count来动态生成索引。
可行的解决方案
方案1:添加反向查找辅助方法(快速适配现有代码)
不需要改动原字典结构,写一个小方法根据英语(Value)找对应的波兰语(Key):
// 根据英语单词查找对应的波兰语单词 private string GetPolishWord(string englishWord, Dictionary<string, string> dict) { // 用FirstOrDefault避免找不到时抛出异常,同时忽略大小写提升用户体验 var match = dict.FirstOrDefault(kv => kv.Value.Equals(englishWord, StringComparison.OrdinalIgnoreCase)); return match.Key; }
然后修改反向校验的逻辑:
// 假设textBox1输入英语,textBox2输入波兰语,验证是否正确 var expectedPolish = GetPolishWord(textBox1.Text, myDict); if (!string.IsNullOrEmpty(expectedPolish) && textBox2.Text.Equals(expectedPolish, StringComparison.OrdinalIgnoreCase)) { MessageBox.Show("Dobrze"); var rnd = new Random(); // 用字典Count动态生成索引,适配任意数量的单词 int randomIndex = rnd.Next(0, myDict.Count); string randomPolish = myDict.Keys.ElementAt(randomIndex); textBox2.Text = randomPolish; } else { MessageBox.Show("Nieprawidłowe słowo!"); }
提示:如果你的翻译是一一对应的(没有重复的英语单词),这个方法完全够用;如果有重复Value,
FirstOrDefault会返回第一个匹配的Key,按需调整即可。
方案2:实现双向字典(高效频繁查找)
如果需要经常做双向翻译,推荐自定义一个双向字典类,让正反查找都是O(1)的效率:
public class BidirectionalDict<TKey, TValue> { private readonly Dictionary<TKey, TValue> _forward = new(); private readonly Dictionary<TValue, TKey> _reverse = new(); public void Add(TKey key, TValue value) { _forward.Add(key, value); _reverse.Add(value, key); } // 正向查找:Key→Value public bool TryGetForward(TKey key, out TValue value) => _forward.TryGetValue(key, out value); // 反向查找:Value→Key public bool TryGetReverse(TValue value, out TKey key) => _reverse.TryGetValue(value, out key); public IEnumerable<TKey> Keys => _forward.Keys; public IEnumerable<TValue> Values => _forward.Values; public int Count => _forward.Count; }
使用这个类的代码示例:
BidirectionalDict<string, string> myDict = new(); myDict.Add("Pies", "Dog"); myDict.Add("Kot", "Cat"); // ... 其他单词省略 // 英语→波兰语校验逻辑 if (myDict.TryGetReverse(textBox1.Text, out var expectedPolish) && textBox2.Text.Equals(expectedPolish, StringComparison.OrdinalIgnoreCase)) { MessageBox.Show("Dobrze"); var rnd = new Random(); int randomIndex = rnd.Next(0, myDict.Count); string randomPolish = myDict.Keys.ElementAt(randomIndex); textBox2.Text = randomPolish; } else { MessageBox.Show("Nieprawidłowe lub nieznane słowo!"); }
这个方案适合单词量较大、需要频繁双向查找的场景,性能更优。
方案3:临时反转字典(简单场景应急)
如果只是偶尔需要反向查找,可以临时生成一个反转字典:
// 生成英语→波兰语的反转字典 var reverseDict = myDict.ToDictionary(kv => kv.Value, kv => kv.Key); // 校验逻辑 if (reverseDict.TryGetValue(textBox1.Text, out var expectedPolish) && textBox2.Text.Equals(expectedPolish, StringComparison.OrdinalIgnoreCase)) { // 后续逻辑和之前一致 }
注意:这个方法只适合翻译一一对应的场景,如果原字典有重复的英语Value,会直接抛出异常,因为字典Key必须唯一。
额外优化小技巧
- 避免重复创建Random:如果这段校验代码会被频繁触发,每次
new Random()可能生成重复的随机数,建议把Random实例声明为类的成员变量。 - 忽略大小写比较:用户输入可能有大小写失误(比如输入"dog"而非"Dog"),用
StringComparison.OrdinalIgnoreCase可以提升用户体验,减少不必要的错误提示。
内容的提问来源于stack exchange,提问作者nnexxe 7
相关产品推荐
相关产品推荐

