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

泛型方法报错:无法从Game/CustomObject隐式转换为System.IConvertible

问题解决:泛型方法返回自定义类型的转换错误

问题根源

报错There is no implicit conversion from uCue_Silver.Models.Game to System.IConvertible的核心原因有两个:

  1. 泛型方法GetResources<T>添加了错误的约束:where T : IConvertible。IConvertible接口是为值类型(如int、string、DateTime等)设计的,自定义类Game、Word既没有实现也不需要实现这个接口,因此调用时会触发类型约束不匹配的错误。
  2. 误用Convert.ChangeType:该方法用于值类型之间的转换,不适用于自定义引用类型的强制转换,完全没必要使用。

解决方案

1. 修改泛型方法的约束与转换逻辑

移除不必要的IConvertible约束,直接对目标对象进行类型转换,同时添加类型检查增强安全性:

// 移除where T : IConvertible约束
public T GetResources<T>(int level = 1, int word = 1, string gameVersion = "bronze", bool shouldReturnGamesOnly = false)
{
    if (!versions.Contains(gameVersion))
        throw new GameVersionOutOfRangeException();

    if (gameVersion.ToLower() == "bronze")
    {
        if (BronzeGameLevels == null)
            throw new NullReferenceException("Bronze Game Levels are Null. Potential missing data in BronzeLevels.json file.");

        if (!shouldReturnGamesOnly)
        {
            var targetWord = BronzeGameLevels.Games[level - 1].words[word - 1];
            // 类型检查,避免传入错误的T类型
            if (targetWord is not T)
                throw new InvalidCastException($"Cannot convert Word to {typeof(T).Name}");
            return (T)(object)targetWord;
        }
        else
        {
            var targetGame = BronzeGameLevels.Games[level - 1];
            if (targetGame is not T)
                throw new InvalidCastException($"Cannot convert Game to {typeof(T).Name}");
            return (T)(object)targetGame;
        }
    }
    else if (gameVersion.ToLower() == "silver")
    {
        // 补充Silver版本的逻辑示例
        // if (SilverGameLevels == null)
        //     throw new NullReferenceException("Silver Game Levels are Null...");
        // return shouldReturnGamesOnly ? (T)(object)SilverGameLevels.Games[level-1] : (T)(object)SilverGameLevels.Games[level-1].words[word-1];
        throw new NotImplementedException("Silver version not implemented yet");
    }

    throw new UnreachableCodeException();
}

2. 验证调用逻辑

修改后的方法可正常调用,原调用代码无需改动:

方法1(获取Word)

public string GetWord(int level, int word, string gameVersion = "bronze")
{
    var res = GetResources<Word>(level, word, gameVersion); // 不再报错
    return res.word;
}

方法2(获取Game)

public int GetTotalWordsInCurrentGame(int level, string gameVersion = "bronze")
{
    var res = GetResources<Game>(level, gameVersion: gameVersion); // 不再报错
    return res.words.Count;
}

额外优化建议

  • 避免使用async void:LoadLevelsAsync方法用async void会导致无法捕获异步异常,建议改成async Task:
    async Task LoadLevelsAsync()
    {
        IJsonReader reader = DependencyService.Get<IJsonReader>();
        var bronzeLevels = await reader.ReadJsonFile("BronzeLevels.json");
        BronzeGameLevels = JsonConvert.DeserializeObject<Level>(bronzeLevels);
    }
    
  • 提前初始化数据:确保在调用GetResources<T>之前,BronzeGameLevels已经完成初始化,避免空引用异常。
  • 扩展类型支持:如果后续需要支持更多类型,可以添加对Level类型的判断逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 01:25:22