c# - 字节数组的扩展方法有问题

标签 c# extension-methods bytearray

我正在使用一个发送回图像的设备,当我请求图像时,图像数据之前有一些未记录的信息。我只能通过查看二进制数据并识别其中的图像头信息来实现这一点。

我本来有一个普通的方法,把它转换成一个扩展方法。这里最初的问题与编译器提示没有将 Array 作为第一个参数(我有 Byte[])有关,但事实证明我犯了一个错误,忘记删除调用代码中的第一个参数。换句话说,我曾经有:

Byte[] new_buffer = RemoveUpToByteArray(buffer, new byte[] { 0x42, 0x4D });

改成扩展方法后,我错误地使用了:

buffer.RemoveUpToByteArray( buffer, new byte[] { 0x42, 0x4D });

无论如何,现在一切都解决了,因为我在将代码示例输入 SO 时意识到了我的错误。 但是,我有一个新问题,就是缺乏对扩展方法和引用与值类型的理解。这是代码:

public static void RemoveFromByteArrayUntil(this Byte[] array, Byte[] until)
{
    Debug.Assert(until.Count() > 0);
    int num_header_bytes = until.Count();
    int header_start_pos = 0; // the position of the header bytes, defined by [until]
    byte first_header_byte = until[0];
    while(header_start_pos != -1) {
        header_start_pos = Array.IndexOf(array, first_header_byte, header_start_pos);
        if(header_start_pos == -1)
            break;
        // if we get here, then we've found the first header byte, and we need to look
        // for the next ones sequentially
        for(int header_ctr=1; header_ctr<num_header_bytes; header_ctr++) {
            // we're going to loop over each of the header bytes, but will
            // bail out of this loop if there isn't a match
            if(array[header_start_pos + header_ctr] != until[header_ctr]) {
                // no match, so bail out.  but before doing that, advance
                // header_start_pos so the outer loop won't find the same
                // occurrence of the first header byte over and over again
                header_start_pos++;
                break;
            }
        }
        // if we get here, we've found the header!
        // create a new byte array of the new size
        int new_size = array.Count() - header_start_pos;
        byte[] output_array = new byte[new_size];
        Array.Copy(array, header_start_pos, output_array, 0, new_size);
        // here is my problem -- I want to change what array points to, but
        // when this code returns, array goes back to its original value, which
        // leads me to believe that the first argument is passed by value.
        array = output_array;
        return;
    }
    // if we get here, we didn't find a header, so throw an exception
    throw new HeaderNotInByteArrayException();
}

我现在的问题是扩展方法的第一个 this 参数看起来是按值传递的。我想重新分配数组指向的内容,但在这种情况下,看起来我只能操作数组的数据。

最佳答案

扩展方法是静态方法,只是看起来是实例方法。您可以将扩展方法正在处理的实例视为只读(按值)。分配给作为扩展的第一个参数的 byte[] 的实例方法将不起作用。你将无法摆脱分配,但你可以修改你的扩展然后像这样写你的分配:

buffer = buffer.RemoveUpToByteArray(header);

让您的扩展程序返回字节数组结果,并且不要尝试分配给扩展程序内的缓冲区。你的扩展将是这样的:

public static class MyExtensionMethods
{
    public static byte[] RemoveUpToByteArray(this byte[] buffer, byte[] header)
    {
        byte[] result = buffer;

        // your logic to remove header from result

        return result;
    }
}

希望对您有所帮助。

编辑: 以上仅适用于值类型。如果您要扩展的类型是引用类型,那么您将不会像上面尝试的那样直接对该类型进行操作。遗憾的是,字节数组是一个结构,因此派生自 System.ValueType。考虑以下内容,这在扩展中是完全合法的,并且会给出预期的结果:

public class MyBytes
{
    public byte[] ByteArray { get; set; }
}

public static class MyExtensionMethods
{
    // Notice the void return here...
    public static void MyClassExtension(this MyBytes buffer, byte[] header)
    {
        buffer.ByteArray = header;
    }
}

关于c# - 字节数组的扩展方法有问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2578726/

相关文章:

android - 如何从 byte[] 创建 Drawable ? (安卓)

c# - Jetbrains Rider 指定运行时构建参数

c# - 异常可抛构造函数和初始化。最佳实践

c# - MethodInfo.MetadataToken 的目的是什么

Python快速散列可变对象

java - 如何在 Java 中声明无限大小/动态的字节数组?

c# - COM互操作注册

c# - 我怎样才能使这个扩展方法更通用?

c# - 接口(interface)扩展方法,具有匹配的通用参数

c# - 为什么在 IEnumerables 上使用标准扩展方法