什么是C#中的memset?

我需要byte[]用一个非零值填充。如何在C#中做到这一点而又不遍历byte数组中的每个数组?


更新:评论似乎将其分为两个问题-


是否有一种Framework方法来填充可能类似于的byte [] memset

当我们处理非常大的数组时,最有效的方法是什么?

我完全同意,正如Eric和其他人指出的那样,使用简单的循环就可以了。问题的关键是看我是否可以学习有关C#的新知识:)我认为Juliet的并行操作方法应该比简单的循环还要快。


基准测试: 感谢Mikael Svenson:http : //techmikael.blogspot.com/2009/12/filling-array-with-default-value.html


事实证明,for除非您要使用不安全的代码,否则简单的循环是必经之路。


抱歉,我的原始帖子不够清晰。Eric和Mark的评论都是正确的。当然需要有更集中的问题。感谢大家的建议和回应。


呼如林
浏览 871回答 3
3回答

四季花海

您可以使用Enumerable.Repeat:byte[] a = Enumerable.Repeat((byte)10, 100).ToArray();第一个参数是您想要重复的元素,第二个参数是重复它的次数。对于小型阵列,这是可以的,但是如果要处理大型阵列,并且性能是一个问题,则应使用循环方法。

撒科打诨

实际上,很少有称为Initblk(英文版)的IL操作可以做到这一点。因此,让我们将其用作不需要“不安全”的方法。这是帮助程序类:public static class Util{&nbsp; &nbsp; static Util()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var dynamicMethod = new DynamicMethod("Memset", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; null, new [] { typeof(IntPtr), typeof(byte), typeof(int) }, typeof(Util), true);&nbsp; &nbsp; &nbsp; &nbsp; var generator = dynamicMethod.GetILGenerator();&nbsp; &nbsp; &nbsp; &nbsp; generator.Emit(OpCodes.Ldarg_0);&nbsp; &nbsp; &nbsp; &nbsp; generator.Emit(OpCodes.Ldarg_1);&nbsp; &nbsp; &nbsp; &nbsp; generator.Emit(OpCodes.Ldarg_2);&nbsp; &nbsp; &nbsp; &nbsp; generator.Emit(OpCodes.Initblk);&nbsp; &nbsp; &nbsp; &nbsp; generator.Emit(OpCodes.Ret);&nbsp; &nbsp; &nbsp; &nbsp; MemsetDelegate = (Action<IntPtr, byte, int>)dynamicMethod.CreateDelegate(typeof(Action<IntPtr, byte, int>));&nbsp; &nbsp; }&nbsp; &nbsp; public static void Memset(byte[] array, byte what, int length)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var gcHandle = GCHandle.Alloc(array, GCHandleType.Pinned);&nbsp; &nbsp; &nbsp; &nbsp; MemsetDelegate(gcHandle.AddrOfPinnedObject(), what, length);&nbsp; &nbsp; &nbsp; &nbsp; gcHandle.Free();&nbsp; &nbsp; }&nbsp; &nbsp; public static void ForMemset(byte[] array, byte what, int length)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; for(var i = 0; i < length; i++)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; array[i] = what;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; private static Action<IntPtr, byte, int> MemsetDelegate;}表现如何?这是Windows / .NET和Linux / Mono(不同PC)的结果。Mono/for:&nbsp; &nbsp; &nbsp;00:00:01.1356610Mono/initblk: 00:00:00.2385835&nbsp;.NET/for:&nbsp; &nbsp; &nbsp;00:00:01.7463579.NET/initblk: 00:00:00.5953503因此值得考虑。请注意,生成的IL将不可验证。

收到一只叮咚

有点晚了,但是下面的方法可能是一个不错的折衷方案,而无需恢复为不安全的代码。基本上,它使用常规循环初始化数组的开头,然后恢复为Buffer.BlockCopy(),该速度应与使用托管调用所能获得的速度一样快。public static void MemSet(byte[] array, byte value) {&nbsp; if (array == null) {&nbsp; &nbsp; throw new ArgumentNullException("array");&nbsp; }&nbsp; const int blockSize = 4096; // bigger may be better to a certain extent&nbsp; int index = 0;&nbsp; int length = Math.Min(blockSize, array.Length);&nbsp; while (index < length) {&nbsp; &nbsp; array[index++] = value;&nbsp; }&nbsp; length = array.Length;&nbsp; while (index < length) {&nbsp; &nbsp; Buffer.BlockCopy(array, 0, array, index, Math.Min(blockSize, length-index));&nbsp; &nbsp; index += blockSize;&nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP