泛型方法报错:无法从Game/CustomObject隐式转换为System.IConvertible
问题解决:泛型方法返回自定义类型的转换错误
问题根源
报错There is no implicit conversion from uCue_Silver.Models.Game to System.IConvertible的核心原因有两个:
- 泛型方法
GetResources<T>添加了错误的约束:where T : IConvertible。IConvertible接口是为值类型(如int、string、DateTime等)设计的,自定义类Game、Word既没有实现也不需要实现这个接口,因此调用时会触发类型约束不匹配的错误。 - 误用
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
相关产品推荐
相关产品推荐

