我知道问题的标题不是很清楚,但让我尽量解释一下。
我正在开发一个修改文件字节的应用程序。为此,我有两个类:Mod 和 Action。
Action 存储在 Mod 的实例中,这告诉应用程序在哪个特定地址修改哪些字节:
public class Action
{
public Action(int address, params byte[] bytes)
{
Address = address;
Bytes = bytes;
}
public int Address { get; }
public byte[] Bytes { get; }
}
public class Mod
{
public Mod(string name, List<Action> actions)
{
Name = name;
Actions = actions;
}
public string Name { get; }
public List<Action> Actions { get; }
}
现在,我想写一些字节,它们变得相当重复,所以在创建 Action 实例时,我没有将它们分配给 bytes,而是将所述字节数组存储在名为 OpCodes 的静态类中:
public static class OpCodes
{
public static byte[] BX_LR = {0x70, 0x47};
}
所以现在我想要实现的是:
new Action(0x1AF0F0, 0x01, 0x20, OpCodes.BX_LR) //Return 1. (true)
如您所见,我想使用字节 0x01、0x20 然后我还想使用 BX_LR 的值,但是,编译器不喜欢这样。
我明白了:
Argument 4: cannot convert from 'byte[]' to 'byte'
我怎样才能做到这一点?
请您参考如下方法:
我在 LinqPad 中想到了这个:
void Main()
{
var x = new Action(0x1AF0F0, 0x01, 0x20, OpCode.BX_LR); //Return 1. (true)
Console.WriteLine(x);
}
public class Action
{
public Action(int address, params OpCode[] bytes)
{
Address = address;
Bytes = OpCode.Flatten(bytes);
}
public int Address { get; set; }
public byte[] Bytes { get; set; }
}
public class Mod
{
public Mod(string name, List<Action> actions)
{
Name = name;
Actions = actions;
}
public string Name { get; set; }
public List<Action> Actions { get; set; }
}
public class OpCode
{
private byte[] _value;
private OpCode(byte[] value)
{
_value = value;
}
public static byte[] BX_LR = {0x70, 0x47};
public static implicit operator OpCode (byte value)
{
return new OpCode(new []{value});
}
public static implicit operator OpCode (byte[] value)
{
return new OpCode(value);
}
public static byte[] Flatten (OpCode[] opCodes)
{
var result = new List<byte>(opCodes.Length);
foreach (var opCode in opCodes)
{
result.AddRange(opCode._value);
}
return result.ToArray();
}
}
LinqPad中的输出如下:
Address
1765616
Bytes
01 20 70 47
代码使用 OpCode 类(我将 OpCodes 重命名为单数)作为 byte[] 和 byte< 之间的中介。这有助于很好的调用。
Action 的构造函数采用 OpCode 的 params 和任何 byte 或 byte[] 将隐式转换为 OpCode 因此您可以将字节放入调用中...然后在构造中您可以将结构扁平化为单个 byte[ ] 使用专用调用。
注意:由于 LinqPad 的提示,我将 set; 添加到属性中。
这样做的好处在于调用的可读性,但正如您所看到的那样存在开销......该开销仅对长字节序列有意义。
顺便说一句。您可以将 _value 设置为只读,我还建议将 OpCode
设置为 sealed
struct。原因是使用代码中显示的 OpCode 将创建一堆短暂的对象,但如果它们是 struct 那么它们将不会加载垃圾收集器。此外,不允许派生类型。编辑:该结构的缺点是您无法控制默认构造函数,这将使用 _values 将其初始化为 null。
另一个建议是将公共(public)静态字段定义为readonly(不允许替换它们)和OpCode,这将节省转换并防止篡改数组。
