3 回答
TA贡献1811条经验 获得超5个赞
您可以使用Enumerable.Repeat:
byte[] a = Enumerable.Repeat((byte)10, 100).ToArray();
第一个参数是您想要重复的元素,第二个参数是重复它的次数。
对于小型阵列,这是可以的,但是如果要处理大型阵列,并且性能是一个问题,则应使用循环方法。
TA贡献1934条经验 获得超2个赞
实际上,很少有称为Initblk(英文版)的IL操作可以做到这一点。因此,让我们将其用作不需要“不安全”的方法。这是帮助程序类:
public static class Util
{
static Util()
{
var dynamicMethod = new DynamicMethod("Memset", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
null, new [] { typeof(IntPtr), typeof(byte), typeof(int) }, typeof(Util), true);
var generator = dynamicMethod.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Ldarg_2);
generator.Emit(OpCodes.Initblk);
generator.Emit(OpCodes.Ret);
MemsetDelegate = (Action<IntPtr, byte, int>)dynamicMethod.CreateDelegate(typeof(Action<IntPtr, byte, int>));
}
public static void Memset(byte[] array, byte what, int length)
{
var gcHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
MemsetDelegate(gcHandle.AddrOfPinnedObject(), what, length);
gcHandle.Free();
}
public static void ForMemset(byte[] array, byte what, int length)
{
for(var i = 0; i < length; i++)
{
array[i] = what;
}
}
private static Action<IntPtr, byte, int> MemsetDelegate;
}
表现如何?这是Windows / .NET和Linux / Mono(不同PC)的结果。
Mono/for: 00:00:01.1356610
Mono/initblk: 00:00:00.2385835
.NET/for: 00:00:01.7463579
.NET/initblk: 00:00:00.5953503
因此值得考虑。请注意,生成的IL将不可验证。
TA贡献1821条经验 获得超4个赞
有点晚了,但是下面的方法可能是一个不错的折衷方案,而无需恢复为不安全的代码。基本上,它使用常规循环初始化数组的开头,然后恢复为Buffer.BlockCopy(),该速度应与使用托管调用所能获得的速度一样快。
public static void MemSet(byte[] array, byte value) {
if (array == null) {
throw new ArgumentNullException("array");
}
const int blockSize = 4096; // bigger may be better to a certain extent
int index = 0;
int length = Math.Min(blockSize, array.Length);
while (index < length) {
array[index++] = value;
}
length = array.Length;
while (index < length) {
Buffer.BlockCopy(array, 0, array, index, Math.Min(blockSize, length-index));
index += blockSize;
}
}
- 3 回答
- 0 关注
- 870 浏览
添加回答
举报