C# 使用';参数';关键字以包括单个值以及值集合
我知道问题的标题不是很清楚,但让我尽量解释清楚 我正在开发一个修改文件字节的应用程序。为此,我有两个类:C# 使用';参数';关键字以包括单个值以及值集合,c#,C#,我知道问题的标题不是很清楚,但让我尽量解释清楚 我正在开发一个修改文件字节的应用程序。为此,我有两个类:Mod和Action 操作存储在Mod的实例中,它告诉应用程序在哪个特定地址修改哪个字节: public class Action { public Action(int address, params byte[] bytes) { Address = address; Bytes = bytes; } public int
Mod
和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; }
}
因此,我现在正努力实现以下目标:
new Action(0x1AF0F0, 0x01, 0x20, OpCodes.BX_LR) //Return 1. (true)
如您所见,我想使用字节0x01
,0x20
,然后我还想使用BX_LR
的值,但是编译器不喜欢这样
我明白了:
参数4:无法从“byte[]”转换为“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();
}
}
代码使用类
操作码
(我将操作码
重命名为单数)作为字节[]
和字节
之间的中介。这是一个很好的调用
其思想是Action
的构造函数采用OpCode
的params
,任何byte
或byte[]
都将隐式转换为OpCode
,因此您可以在调用中放入字节。。。然后在构造中,您可以通过专用调用将结构平坦化为单个字节[]
注:我增加了set由于LinqPad的投诉,代码>更改为属性
好处在于调用的可读性,但正如您所看到的,这会带来开销。。。这种开销只适用于长系列的字节
顺便说一句,您可以将\u值设置为只读,我还建议将操作码设置为密封的结构。原因是使用代码中显示的OpCode
将创建一组短期对象,但如果它们是struct
,则不会加载垃圾收集器。另外,不允许使用derivec类型。编辑:该结构的缺点是无法控制默认构造函数,这将使用\u值将其初始化为null
另一个建议是将公共静态字段定义为readonly
(不允许替换它们)和OpCode
,这将保存强制转换并防止篡改数组。我将使用扩展方法将这些字节预加/追加到数组中:
public static class Extensions
{
public static byte[] Prepend(this byte[] that, params byte[] data)
{
byte[] modified;
modified = new byte[that.Length + data.Length];
Array.Copy(data, modified, data.Length);
Array.Copy(that, 0, modified, data.Length, that.Length);
return modified;
}
public static byte[] Append(this byte[] that, params byte[] data)
{
byte[] modified;
modified = new byte[that.Length + data.Length];
Array.Copy(that, modified, that.Length);
Array.Copy(data, 0, modified, that.Length, data.Length);
return modified;
}
}
您现在可以这样使用它们:
new Action(0x1AF0F0, OpCodes.BX_LR.Prepend(0x01, 0x20))
或者这个:
new Action(0x1AF0F0, OpCodes.BX_LR.Append(0x01, 0x20))
编译器不喜欢这样?我添加了编译器所说的内容。框架中已经有一个Action
类。你可能想改变这一点,但这不是必须的!将0x01,0x20添加到字节数组,然后传递新操作(0x1AF0F0,(new[]{0x01,0x20}).Concat(OpCodes.BX_LR).ToArray())
?太棒了!非常感谢。@Therplexed还有一件事,这将创建一组短期对象。NET垃圾回收器在这方面做得很好,但如果出现问题,您可以保留一个包含256个单字节操作码的数组,并实现隐式的按数组强制转换查找。编辑:我刚刚意识到,使用struct可以更好地解决这个问题。投票支持使用隐式类型转换,这是不常见的。
new Action(0x1AF0F0, OpCodes.BX_LR.Prepend(0x01, 0x20))
new Action(0x1AF0F0, OpCodes.BX_LR.Append(0x01, 0x20))