使用字节数组的扩展方法时遇到问题

Dav*_*ave 5 c# extension-methods bytearray

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

我最初有一个普通的方法,并将其转换为扩展方法.这里的原始问题与编译器抱怨没有将Array作为第一个参数(我有Byte [])有关,但事实证明我犯了错误而忘记删除调用代码中的第一个参数.换句话说,我曾经有过:

Byte[] new_buffer = RemoveUpToByteArray(buffer, new byte[] { 0x42, 0x4D });
Run Code Online (Sandbox Code Playgroud)

在更改为扩展方法后,我错误地使用了:

buffer.RemoveUpToByteArray( buffer, new byte[] { 0x42, 0x4D });
Run Code Online (Sandbox Code Playgroud)

无论如何,现在这一切都已修复,因为我在将代码示例输入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();
}
Run Code Online (Sandbox Code Playgroud)

我现在的问题是,看起来扩展方法的第一个参数是通过值传递的.我想重新分配哪些数组指向,但在这种情况下,看起来我只需要操纵数组的数据.

Aud*_*die 5

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

buffer = buffer.RemoveUpToByteArray(header);
Run Code Online (Sandbox Code Playgroud)

使扩展返回字节数组结果,不要尝试分配扩展名内的缓冲区.您的扩展程序将是这样的:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.

编辑:以上只适用于值类型.如果您要扩展的类型是引用类型,那么您不会像上面尝试的那样直接对该类型进行操作.遗憾的是,字节数组是一个结构,因此派生自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;
    }
}
Run Code Online (Sandbox Code Playgroud)