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

Roslyn CompletionService无法推断foreach隐式变量类型问题

问题根因

foreach循环隐式变量补全失效,是两个配置缺失共同导致的:

  • 元数据引用不全:你只加载了核心运行时和自定义业务程序集,没有加载System.Collections、System.Runtime等定义泛型集合类型的基础程序集。Roslyn推断foreach变量类型时,需要解析IEnumerable<T>的GetEnumerator()方法返回值、Current属性类型,缺少对应元数据时无法完成类型推导;而普通变量赋值的类型推断直接读取属性的声明类型,不依赖集合相关逻辑,所以能正常工作。
  • MEF服务加载不全:你只在默认MEF程序集列表里加了自定义业务程序集,没有加载C#语义分析、补全服务对应的Features程序集。foreach场景的隐式类型补全逻辑在C# Features程序集中,Visual Studio默认加载所有相关Features程序集,所以可以正常出补全结果。
修复方案

按以下步骤调整配置即可:

  1. 补全必要的元数据引用
    不要只加载object类型所在的核心程序集,把泛型、集合相关的基础程序集都加入引用列表:
var runtimeRoot = Path.GetDirectoryName(typeof(object).Assembly.Location);
var metadataRefs = new List<MetadataReference>
{
    MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
    MetadataReference.CreateFromFile(Path.Combine(runtimeRoot, "System.Runtime.dll")),
    MetadataReference.CreateFromFile(Path.Combine(runtimeRoot, "System.Collections.dll")),
    MetadataReference.CreateFromFile(Path.Combine(runtimeRoot, "System.Linq.dll")),
    MetadataReference.CreateFromFile(typeof(ScriptEngine).Assembly.Location)
};
// 后续把这个metadataRefs传给WithMetadataReferences即可
  1. 补全MEF加载的程序集列表
    把Roslyn C#编译、补全服务对应的程序集加入MEF加载列表:
var assemblies = new List<Assembly>(MefHostServices.DefaultAssemblies);
// 加入C#编译核心、补全服务核心程序集
assemblies.Add(typeof(CSharpCompilation).Assembly);
assemblies.Add(typeof(CompletionService).Assembly);
assemblies.Add(typeof(ScriptEngine).Assembly);
var host = MefHostServices.Create(assemblies);
this.workspace = new AdhocWorkspace(host);
  1. 移除不必要的编译选项配置
    你当前给submission(脚本)项目手动指定了OutputKind.DynamicallyLinkedLibrary,这会和脚本模式的语义解析逻辑冲突,去掉该配置,用submission项目默认的输出类型即可。
验证方式

调整配置后,可以在调用GetCompletionsAsync前先校验语义模型的推断结果:

var syntaxRoot = await document.GetSyntaxRootAsync();
// 找到光标位置对应的语法Token
var token = syntaxRoot.FindToken(position);
var semanticModel = await document.GetSemanticModelAsync();
// 获取光标位置的类型信息
var typeInfo = semanticModel.GetTypeInfo(token.Parent);
// 如果typeInfo.Type显示为Measure类型,说明类型推断正常,补全服务会正常返回成员列表

额外注意:如果你的脚本支持顶层变量、模式匹配等新语法,要确保CSharpParseOptions指定的LanguageVersion和你引用的Roslyn版本匹配,避免语法解析失败导致后续补全失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 19:54:14