使用BinaryReader读/写一个可空类型

本文关键字:一个 类型 BinaryReader 使用 | 更新日期: 2023-09-27 18:08:28

我正在超载系统。IO BinaryReader序列化一些类用于文件存储。我在处理诸如字典之类的项时没有遇到任何问题,但是在处理可空类型时没有成功。有可能做到吗?具体来说,是十进制吗?和字符串?,但任何类型都应该适合我的解决方案

由于特定的业务原因,我必须进行二进制序列化,因此请将响应限制为仅适用于该解决方案的解决方案。

例如

…对于读写字节数组,我使用以下方法:

    public byte[] ReadByteArray()
    {
        int len = ReadInt32();
        if (len > 0) return ReadBytes(len);
        if (len < 0) return null;
        return new byte[0];
    }
    public override void Write(byte[] b)
    {
        int len = b.Length;
        Write(len);
        if (len > 0) base.Write(b);
    }

使用BinaryReader读/写一个可空类型

您需要添加某种标志,让阅读器知道是否应该读取下一个字节。

public decimal? ReadNullableDecimal()
{
    bool hasValue = ReadBoolean();
    if (hasValue) return ReadDecimal();
    return null;
}
public void Write(decimal? val)
{
    bool hasValue = val.HasValue;
    Write(hasValue)
    if(hasValue)
        Write(val.Value);
}

然而,我们可以聪明一点,创建一个适用于所有基于结构的类型的泛型方法

public Nullable<T> ReadNullable<T>(Func<T> ReadDelegate) where T : struct
{
    bool hasValue = ReadBoolean();
    if (hasValue) return ReadDelegate();
    return null;
}
public void Write<T>(Nullable<T> val) where T : struct
{
    bool hasValue = val.HasValue;
    Write(hasValue)
    if(hasValue)
        Write(val.Value);
}

如果我想用我的ReadNullable函数读取Int32,我将其命名为

Int32? nullableInt = customBinaryReader.ReadNullable(customBinaryReader.ReadInt32);

它将测试值是否存在,如果存在则调用传入的函数


EDIT:睡觉后,Write<T>方法可能不像你期望的那样工作。因为T不是一个定义良好的类型,所以唯一可以支持它的方法是Write(object),而Binary writer不支持开箱即用。ReadNullable<T>仍然可以工作,如果你想使用Write<T>,你需要使val.Value的结果是动态的。您需要进行基准测试,看看是否有任何性能问题。

public void Write<T>(Nullable<T> val) where T : struct
{
    bool hasValue = val.HasValue;
    Write(hasValue)
    if(hasValue)
        Write((dynamic)val.Value);
}
public decimal ReadDecimal()
{
    int len = ReadInt32();
    if (len > 0) return base.ReadDecimal();
    if (len < 0) return null;
    return new decimal;
}

public override void WriteDecimal(decimal d)
{
    if (d==null)
        WriteInt32(-1);
    else
    {
        WriteInt32(sizeof(d)); //16
        Write(d);
    }
}