C# 程序似乎正在修改标记为只读的参数

C# program seems to be modifying a parameter marked as readonly

我有一个名为 ARCMF 的函数,它应该 return 为每个相同的输入集 statekeys 都传递相同的伪随机输出使用关键字 in 的只读引用。但是,当我两次尝试 运行 这个函数时,第一个和第二个结果永远不会彼此相等(但每次重新启动程序时都相等)。经过大量调试后,似乎有问题的变量被修改了。我尝试将其设置为只读,但它仍然以某种方式被修改。这让我难住了好几个小时...

All of my code is here on this repo.

This is the variable in question (from now on I will refer to as IV) which I have in a watch window during debugging, and I pass it into a function called ARCMF...

var arc = new ARC128(key, iv);
var mf0 = arc.ARCMF(iv, arc.Schedule(key, iv, 1));
arc.PrintArray(mf0, "Main Function Iteration 0 Results");
var mf1 = arc.ARCMF(iv, arc.Schedule(key, iv, 1));
arc.PrintArray(mf1, "Main Function Iteration 1 Results");
c.WriteLine(Enumerable.SequenceEqual(mf0, mf1) ? "MF Gen success." : "MF Gen fail.");

internal byte[] ARCMF(in byte[] state, in byte[][] keys)
        {
            var output = state;
            for (int i = 0; i < 9; i++)
            {
                ARCLT.Permutate(ref output, ARCLT.MBLTv1, i);
                ARCBMGR(ref output);
                ARCLT.Permutate(ref output, ARCLT.SBLTv1, i);
                output = OTPArray(output, keys[i]);
            }
            return output; 
        }

IV的修改具体发生在ARCLT.Permutate(ref output, ARCLT.MBLTv1, i);

之后

为了帮助展示这一点,这里是一些屏幕截图。

Before ( I cant embed images :( ) and After.

And the function itself looks like this:

internal static void Permutate(ref byte[] io, in byte[] table, int seed =  1)
        {
            seed = (seed == 0) ? 1 : seed;
            for (int i = 0; i <= io.Length - 1; i++)
                io[i] = (byte)((io[i] * seed % 256) ^ table[i]);
        }

对于那些好奇的人,这是程序输出的内容:

Main Function Iteration 0 Results: 785B62AFE54AB7FA7A4EE63D67A311A8
Main Function Iteration 1 Results: F47B4EF85524B92B6F210F9EDCD5786
MF Gen fail.

我该怎么办?

更新 1:将 Permutate 函数更改为

internal static byte[] Permutate(byte[] io, in byte[] table, int seed =  1)
        {
            var o = io;
            seed = (seed == 0) ? 1 : seed;
            for (int i = 0; i <= io.Length - 1; i++)
                o[i] = (byte)((o[i] * seed % 256) ^ table[i]);
            return o;
        }

没有区别。

因为您使用的是 ref 关键字。 它允许 sub-methods 修改内存中的参数值。 在您的情况下,当您每次设置值时,参数 output (输入 byte-structure )被修改两次:

io[i] = (byte)((io[i] * seed % 256) ^ table[i]);.

您正在将它与 Ref 关键字混在一起。 Ref 将修改这些值。

制作副本并使用副本。

var output = new byte[state.Length];
state.CopyTo(output, 0);

or 

var output = state.ToArray();