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更改为属性


好处在于调用的可读性,但正如您所看到的,这会带来开销。。。这种开销只适用于长系列的字节

顺便说一句,您可以将
\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))