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

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必须唯一。


额外优化小技巧

  1. 避免重复创建Random:如果这段校验代码会被频繁触发,每次new Random()可能生成重复的随机数,建议把Random实例声明为类的成员变量。
  2. 忽略大小写比较:用户输入可能有大小写失误(比如输入"dog"而非"Dog"),用StringComparison.OrdinalIgnoreCase可以提升用户体验,减少不必要的错误提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 00:07:31