c# - 为什么带有protobuf的redis将空数组保存为null?
问题描述
我正在使用 StackExchange.Redis 1.2.6 在 redis 服务器 2.8.2103 上使用 protobuf- net 2.3.3维护应用程序。
对于像这样的对象:
[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class Cachable { Foo[] Foos { get; set; } }
当我使用简单的保存时:
using (var memoryStream = new MemoryStream())
{
Serializer.Serialize(memoryStream, cachable);
database.HashSetAsync("category", "key", memoryStream.ToArray());
}
然后检索:
var response = database.HashGet("category", "key");
if (!response.HasValue) return null;
using (var memoryStream = new MemoryStream(response, false))
{
return Serializer.Deserialize<Cachable>(memoryStream);
}
如果缓存数组Foos
有一个空实例,如new Foo[0]
,一旦Cachable
反序列化,数组变为null
。这会改变应用程序某些部分的行为并产生错误。
这种行为是预期的吗?有没有办法改变它?
解决方案
Foo[0]
真正的问题是事实null
吗?如果是这样:
- protobuf没有
null
;的概念 它不能表示和存储 null,因此默认情况下 protobuf-net 会跳过null 值,使其本质上是一个空数组 - 带有“空包装原语”的轻微警告,protobuf 没有“空”序列的概念;在 .proto 术语中,您正在谈论一个
repeated
具有零元素的字段,这意味着:它根本不存在于有效负载中 - 如果它在有效载荷中不存在,它永远不会反序列化为任何东西 - 因为有效载荷中永远没有任何东西告诉它反序列化
所以:
- 避免
null
,除非您指的是可选的子元素;绝对避免null
在列表/数组/等中 - 不要假设空列表/数组/等将被库初始化为非空值
IMO,对于第二点,以下内容将是合理和务实的:
Foo[] Foos { get; set; } = Array.Empty<Foo>();
(这避免了它初始化为的问题null
)
推荐阅读
- javascript - 将文件加载到 javascript 中并读取第一行
- docker - 卷设备磁盘装载 docker compose 错误 - 不是目录
- c++ - 获取 ATL 类的实例计数
- javascript - 如何在 Django Vue.js 的 DateTimeField 中删除字符“T”?
- javascript - 使用 Materialize 发送 php 表单时的 Toast 消息
- pandas - 在熊猫中拆分关节字符串
- go - 如何调用外部程序并处理其输出?
- javascript - Mongoose.model 输入清理?
- android - 如何使用 ViewPager 在 TabLayout 的选项卡上设置页面标题
- delphi - 变体记录而不是重载的对象类型?