C#构造gRPC StreamingRecognizeRequest请求触发空引用异常排查
问题根因
该空引用异常不属于C#版本gRPC的bug,是C# Protobuf代码生成规则与C#语法特性不匹配导致的用法错误:
- C#静态语言下的Protobuf生成代码中,所有嵌套消息类型的属性默认值为
null,不会在构造外层消息时自动实例化嵌套对象;NodeJS等动态语言的Protobuf库会在赋值嵌套属性时隐式创建父级实例,二者逻辑存在差异。 - 你当前使用的
StreamingConfig = { ... }对象初始化器写法,在C#语法中的语义是「为已存在实例的StreamingConfig属性的内部成员赋值」,不会主动创建StreamingRecognitionConfig实例赋值给该属性。执行到这段初始化逻辑时,StreamingConfig仍为默认null值,直接触发空引用,内部嵌套的Config = { ... }也存在完全相同的问题。
修复方案
所有嵌套消息属性初始化时,显式调用构造函数创建对应实例即可,修改后的代码如下:
await voice.RequestStream.WriteAsync(new StreamingRecognizeRequest { StreamingConfig = new StreamingRecognitionConfig { SingleUtterance = true, InterimResults = true, Config = new RecognitionConfig { Encoding = RecognitionConfig.Types.AudioEncoding.Linear16, MaxAlternatives = 1, SampleRateHertz = 8000, Enhanced = true, SpeechContexts = { } } } });
注意:首条消息不传入
audio_content字段的逻辑完全符合要求。oneof类型的字段同一时间仅允许设置其中一个成员,显式赋值StreamingConfig后,oneof的类型标记会自动切换到对应分支,不会出现字段缺失错误。
补充提示
代码中SpeechContexts = { }的写法不需要修改:Protobuf生成的repeated集合字段,会在构造所属消息时自动初始化为空集合,无需手动new,直接用大括号添加元素、或留空都不会触发空引用。
内容的提问来源于stack exchange,提问作者Ngọc Anh Nguyễn
相关产品推荐
相关产品推荐

