您当前的位置: 首页 >  .net

寒冰屋

暂无认证

  • 0浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

.NET库和向后兼容的技巧——第1部分

寒冰屋 发布时间:2020-11-21 13:49:51 ,浏览量:0

目录

行为不相容

继承剧本

Obsolescence是你的朋友

沟通是关键

文档和未定义的行为

接下来是什么?

这篇博客文章将重点讨论.NET库中的行为不兼容问题。

因此,您编写了一个.NET库,并将其发布给公众,现在您将要制作2.0或1.1版,甚至只是1.0.0.0b。

您将要进行的任何更改都有可能引入以下一种或多种向后不兼容的风险:

  • 行为(您库的行为正在改变)
  • 源代码(您的用户代码可能无法编译)
  • 二进制(您的用户的应用程序可能会在运行时中断)

这篇博客文章将重点讨论行为不兼容问题。我将在以后的文章中介绍其他两种类型:

  • 第2部分——源代码不兼容
  • 第3部分——二进制不兼容
行为不相容

当您的新库的行为与先前版本不同时,就会引入行为不兼容性。

总体而言,无法避免行为上的不兼容。这些变化可能会使大多数用户受益,但仍然是行为变化:

  • 修正错误
  • 提高方法调用的性能
  • 修正错误讯息中的错字
  • 从方法抛出新的异常类型以更好地限定错误

您永远不会知道您的任何用户是否依赖于现有(对于大多数情况而言是不希望的)行为。

继承剧本

继承是很容易忽略行为改变的领域。

例如,您可能已经在您的库中包含一个Stream类,并且按照Microsoft提供的说明,您仅实现了Read方法:

The asynchronous methods ReadAsync(Byte[], Int32, Int32), WriteAsync(Byte[], Int32, Int32), 
and CopyToAsync(Stream) use the synchronous methods Read(Byte[], Int32, 
Int32) and Write(Byte[], Int32, Int32) in their implementations. 
Therefore, your implementations of Read(Byte[], Int32, Int32) and Write(Byte[], 
Int32, Int32) will work correctly with the asynchronous methods.

我将使用以下代码作为示例:一个从另一个流中读取并将ASCII字符转换为大写的流。

public class UppercasingStream : Stream
{
    private readonly Stream BaseStream;
    private const byte UppercaseOffset = (byte)('a' - 'A');

    public UppercasingStream(Stream baseStream) => BaseStream = baseStream;

    public override int Read(byte[] buffer, int offset, int count)
    {
        int len = BaseStream.Read(buffer, offset, count);

        for (int i = 0; i < len; i++)
        {
            byte b = buffer[i + offset];
            if (b >= 'a' && b  'Z')
            {
                buffer[i + offset] = (byte)'_';
            }
        }

        return len;
    }
}

在NormalizingStream类的行为与预期甚至异步使用时:

using (var reader = new StreamReader(
    new NormalizingStream(
        new MemoryStream(
            Encoding.ASCII.GetBytes("matteo.tech.blog"))),
    Encoding.ASCII))
{
    var result = await reader.ReadToEndAsync();
    //Writes "MATTEO_TECH_BLOG"
    Console.WriteLine(result);
}

对我们UppercasingStream类的一个合理改进是将实现该ReadAsync方法:

public override async Task ReadAsync
       (byte[] buffer, int offset, int count, CancellationToken ct)
{
    int len = await BaseStream.ReadAsync(buffer, offset, count, ct);

    for (int i = 0; i < len; i++)
    {
        byte b = buffer[i + offset];
        if (b >= 'a' && b             
关注
打赏
1665926880
查看更多评论
0.0775s