C# 如何扩展字符串以反序列化二进制数据

C# 如何扩展字符串以反序列化二进制数据,c#,extension-methods,C#,Extension Methods,我正在使用自己的扩展方法将字符串(以及更多数据类型)序列化为具有自定义二进制格式(外部,我无法修改该格式)的文件。 我的方法是: public static byte[] Serialize(this string str) { if (str.Length > short.MaxValue) throw new ArgumentOutOfRangeException("str", "Max length allowed is " + short.MaxValue.

我正在使用自己的扩展方法将字符串(以及更多数据类型)序列化为具有自定义二进制格式(外部,我无法修改该格式)的文件。 我的方法是:

public static byte[] Serialize(this string str)
{
    if (str.Length > short.MaxValue)
        throw new ArgumentOutOfRangeException("str", "Max length allowed is " + short.MaxValue.ToString());
    List<byte> data = new List<byte>();
    data.Add(0);
    data.Add(0);
    if (str != null)
    {
        byte[] buffer = Encoding.UTF8.GetBytes(str);
        data.AddRange(buffer);
        data[0] = (byte)(buffer.Length % 256);
        data[1] = (byte)((buffer.Length / 256) >> 8);
    }
    return data.ToArray();
}
结果是

data = { 13, 0, 66, 105, 110, 97, 114, 121, 32, 83, 116, 114, 105, 110, 103 }
现在,我尝试添加另一个扩展方法,以便在读取这些文件时进行反序列化:

public static void Deserialize(this string str, byte[] data)
{
    if (data == null || data.Length < 2)
    {
        str = null;
    }
    else
    {
        short length = (short)(data[0] + (data[1] << 8));
        if (data.Length != length + 2)
            throw new ArgumentException("Invalid data", "data");
        str = Encoding.UTF8.GetString(data, 2, length);
    }
}
str2的预期结果是

“二进制字符串”

实际结果是

空的

但是,在逐步调试时,
str
inside
Deserialize()
在第
str=Encoding.UTF8.GetString(数据,2,长度)行获得正确的值

我也试过:

string str3 = string.Deserialize(data);
但是它不编译,错误消息是

错误1“字符串”不包含“反序列化”的定义

我不知道我做错了什么。有没有办法解决这个问题?

的第一个参数是你正在操作的对象。在这种情况下,它是字节数组
数据
。返回类型是您想要填充到字符串变量中的类型。因此,
反序列化
方法的签名应为:

public static string Deserialize(this byte[] data)
在方法内部,您还需要返回字符串值,因此您的完整方法应该是(注意,我稍微简化了它):


虽然DavidG的变体是100%正确的,但我将补充一些解释。 首先,当您对一个对象调用扩展方法时,实际上会调用一个静态方法,所以

str2.Deserialize(data);
将转化为

ClassThatContainsExtensionMethod.Deserialize(str2, data);
现在让我们记住,C#通过值传递参数,这意味着将创建另一个引用

在您的
反序列化()
方法中,您可以修改新字符串,而不是旧字符串(因为它是副本)

str = Encoding.UTF8.GetString(data, 2, length);
您实际上更改了这个本地str,而原始str保持不变(即
null

FYK,您可以使用
ref
out
关键字通过引用传递方法参数


顺便说一句,您真的确定两个字节的长度就足够了吗?

您根本无法更改方法中的str。str需要是out参数才能从方法中取出。但是我确信您不能将扩展方法参数定义为out。字符串是不可变的,但是即使您传递了一个类,该方法也会失败。除非你将一个参数标记为“代码> OUT/<代码>或<代码> REF,否则该方法将修改原始值的副本,然后将其丢弃。是的,这些文件是由旧C++程序编写的,但它似乎使用了自定义序列化方法。否则我会使用
BinaryReader.ReadString()
。看到你的最后一句话,我意识到我没有在我的
Serialize
方法中检查这一点。我添加了一个补丁。
string str1 = "Binary String";
byte[] data = str1.Serialize();
string str2 = data.Deserialize();
str2.Deserialize(data);
ClassThatContainsExtensionMethod.Deserialize(str2, data);
str = Encoding.UTF8.GetString(data, 2, length);