0

我们最近在 SO 上有几个线程(如下),其中一个常见的建议是不要使用指针。

.net 中的固定块

在 .NET 中,使用指针作为函数参数或使用“ref”关键字有什么区别吗?

.net 中的字符串是否被更改?有什么错误吗?

我最近需要将位图图像白色背景转换为透明。我试过了,我能想到的最优化的实现如下。

public unsafe Bitmap MakeWhiteAreaTransparent(Bitmap source)
{
    Bitmap bitmap = new Bitmap(source.Width, source.Height, PixelFormat.Format32bppArgb);
    BitmapData bitmapdata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    BitmapData data2 = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
    int* numPtr = (int*)bitmapdata.Scan0;
    int* numPtr2 = numPtr + (bitmapdata.Width * bitmapdata.Height);
    int* numPtr3 = (int*)data2.Scan0;
    int num = Color.FromArgb(1, Color.White).ToArgb();
    while (numPtr < numPtr2)
    {
        numPtr++;
        Color color = Color.FromArgb(numPtr[0]);
        if (((color.R < 200) || (color.G < 200)) || (color.B < 200))
        {
            numPtr3[0] = color.ToArgb();
        }
        else
        {
            numPtr3[0] = num;
        }
        numPtr3++;
    }
    source.UnlockBits(bitmapdata);
    bitmap.UnlockBits(data2);
    return bitmap;
}

我想知道我在起诉指针方面是否正确,或者我应该使用字节数组和 System.Runtime.InteropServices.Marshal.Copy 而不是用指针到处乱搞???

4

2 回答 2

2

我的意见如下:您应该以应有的方式使用该语言。C# 应该与安全代码一起使用,将 unsafe 作为最后的手段,因为某些代码需要非常快并且被频繁调用。

让我举一些例子。

  1. 你需要做一些缓慢的操作,但它可以在后台的某个地方运行,不是那么频繁,而且它的速度并不是真的很关键。在这种情况下,您可以只使用安全代码:尽管这种方法可能不会从您的处理器中挤出最后一点性能,但它在实现和(更重要的)维护方面的工作量要少得多。

  2. 您需要加快操作速度,安全执行速度慢得令人无法接受。试图改进算法,你尽了最大努力,但它仍然很慢。您尝试并看到非托管实现相当快。嗯,所以 .NET 不是一个合适的平台来实现你的代码的那部分。您在本机 DLL 或平台上可用的任何东西(可能在纯 C 中)中实现代码,并通过 P/Invoke 使用它。这样,您的不安全代码将使用适当的语言进行编码,您只需通过 P/Invoke 调用该方法,或添加 C++/CLI 包装器,或在 C# 中完成互操作的任何其他方式来使用它。您获得了 (1) 托管业务逻辑和本机非常快速处理代码之间的清晰分离,(2) 更好的可维护性,因为现在您的快速数字处理或数据混洗代码处于适当的环境中。

  3. 好吧,您会发现,即使是这种方法也因某种原因也行不通。那么,在这种特殊情况下,您或许应该考虑在 C# 中使用不安全的代码。但即使这样也无济于事的可能性很高。

于 2012-04-20T14:33:38.950 回答
2

使用不安全的代码没有任何问题。您使用正确的工具来完成这项工作。语言中内置了对不安全代码和指针的支持,这意味着开发人员认为这是一件有用的事情——足够有用,以牺牲实现一些其他特性为代价来实现。

存在不安全代码的地方。正如您所发现的,这是访问位图图像中原始数据的最快方式。是的,有一些方法可以在安全代码中做到这一点,但它们要慢得多。不安全代码也是使用大于 2 GB 的内存缓冲区的唯一方法。

而且,是的,在某些应用程序中,您确实需要一个大小为几 GB 的对象。你可以随心所欲地反驳这一点,我会像在 80 年代嘲笑那些说“谁需要一兆字节的 RAM?”之类的话的白痴一样嘲笑你。

有人会说,如果你发现自己需要不安全的代码,你应该用 C++ 编写一个本地 DLL,然后从你的 .NET 程序中调用它。这是一个愚蠢的想法。首先,您可能没有构建本机 DLL 的工具或知识。其次,这会在您的项目中添加更多依赖项。第三,没有特别的好处。它“更安全”吗?不。

使用完成工作所需的东西。尽一切努力使用安全代码。但是,如果您在尝试了其他所有方法之后发现您需要做的事情需要不安全的代码......使用它!这就是为什么在平台上添加了对它的支持。

于 2012-04-20T16:07:21.183 回答