如何从TextReader形式的流中异步读取布尔值?优化现有冗余代码的方案
如何从TextReader形式的流中异步读取布尔值?优化现有冗余代码的方案
兄弟,我太懂你这种手动抠字符的痛苦了——这段代码虽然能跑,但看着乱,维护起来也闹心。咱们可以通过封装复用逻辑、更聪明的字符读取方式,把它改得简洁又可靠,还保持异步和取消支持的完整。
核心优化思路
- 把跳过前导空白的逻辑单独拎出来做成复用方法,别让主逻辑里堆满循环
- 根据第一个非空白字符,直接确定要读取多少后续字符(比如看到't'就知道还要读3个凑"true"),不用挨个字符判断
- 直接拼字符串对比,比零散的字符检查直观多了,也不容易写错
优化后的完整代码
internal override async ValueTask DeserializeAsync(TextReader textReader, CancellationToken cancellationToken = default) { // 先跳过所有前导空白 await SkipWhitespaceAsync(textReader, cancellationToken); // 读取第一个非空白字符 var firstCharBuffer = new char[1]; var readCount = await textReader.ReadAsync(firstCharBuffer, cancellationToken); if (readCount < 1) throw new EndOfStreamException(); var firstChar = firstCharBuffer[0]; string expectedValue; int requiredRemainingChars; // 根据首字符匹配目标字符串和需要读取的剩余字符数 switch (firstChar) { case 't': expectedValue = "true"; requiredRemainingChars = 3; break; case 'f': expectedValue = "false"; requiredRemainingChars = 4; break; default: throw new InvalidDataException($"解析布尔值时遇到意外字符: '{firstChar}'"); } // 读取剩余的字符 var remainingBuffer = new char[requiredRemainingChars]; readCount = await textReader.ReadAsync(remainingBuffer, cancellationToken); if (readCount < requiredRemainingChars) throw new EndOfStreamException(); // 拼接完整字符串并验证 var fullValue = firstChar + new string(remainingBuffer); if (fullValue != expectedValue) throw new InvalidDataException($"预期值为'{expectedValue}',实际得到'{fullValue}'"); // 设置最终结果 Value = expectedValue == "true"; } // 封装的异步跳过空白方法,其他地方也能复用 private async Task SkipWhitespaceAsync(TextReader reader, CancellationToken cancellationToken) { var buffer = new char[1]; int peekChar; // 先Peek看字符,是空白再读取丢弃,避免读错非空白字符 while ((peekChar = await reader.PeekAsync(cancellationToken)) != -1) { cancellationToken.ThrowIfCancellationRequested(); if (char.IsWhiteSpace((char)peekChar)) { await reader.ReadAsync(buffer, cancellationToken); } else { // 遇到非空白字符,停止跳过 break; } } }
关键改进点说明
- 复用空白跳过逻辑:把原本堆在主方法里的空白处理单独封装,让主逻辑更清爽,以后其他地方要跳空白也能直接用
- 更稳健的字符读取:用
PeekAsync先判断下一个字符是不是空白,避免读了非空白字符还要想办法推回流里的麻烦 - 清晰的分支处理:用switch-case替代零散的if-else,一眼就能看懂首字符对应的处理逻辑
- 直观的字符串验证:把字符拼成完整字符串再对比,比逐个字符判断好读多了,出问题时错误信息也更明确
如果需要支持大小写不敏感的匹配(比如允许"True"或"FALSE"),只需要把字符串对比改成fullValue.Equals(expectedValue, StringComparison.OrdinalIgnoreCase)就行。
内容来源于stack exchange
相关产品推荐
相关产品推荐

