C# 如果我需要另一个 class 中的位图,请使用 Dispose()

C # Use Dispose() if i need Bitmap in another class

我有这个 class 来裁剪图像:

public static Bitmap Crop(Bitmap img_crop, int w, int h, int x, int y)
        {
            Image img_crop = img_crop;
            Bitmap bmp_crop = new Bitmap(w, h, PixelFormat.Format24bppRgb);
            bmp_crop.SetResolution(80, 60);

            Graphics gfx = Graphics.FromImage(bmp_crop);
            gfx.SmoothingMode = SmoothingMode.AntiAlias;
            gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
            gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
            gfx.DrawImage(img_cortar, new Rectangle(0, 0, w, h), x, y, w, h, GraphicsUnit.Pixel);

            //bmp_crop.Save("test.bmp");

            // Dispose to free up resources
            img_crop.Dispose();
            //bmp_crop.Dispose();// <------------ How to use this and pass Bitmap to the next class?
            gfx.Dispose();

            Class2(bmp_crop);
            
            return bmp_crop;

        }

我需要在另一个class中裁剪图像,如果我使用Dispose()(bmp_crop.Dispose();),在接下来的class中我得到一个参数错误,我该如何丢弃Bitmap 并且仍然可以在下一个 class?

中使用它
public static Bitmap Class2(Bitmap bmp_crop)
    {
    ...
    }
  • 看看您的代码实际做了什么,它是 调整 图像的大小,而不是裁剪它 - 因此您应该将此方法重命名为 Resize,而不是 Crop.
  • 只有 IDisposable 对象的“所有者”才能调用 .Dispose() 或使用 using 块。
    • “所有者”是指控制 IDisposable 对象生命周期的父作用域或生命周期。
      • 这可以是一个 class(如果 IDisposable 存储为一个字段)或者它是一个方法(如果 IDisposable 不应该超过方法或范围在方法内)。
    • 因为我假设您不打算让您的 Crop 方法限制 Bitmap img_crop(源输入图像)的生命周期,您的 Crop 方法 必须不调用bmp_crop.Dispose()!
  • 当一个方法创建一个新的 IDisposable 对象并 return 时,该方法将“拥有”该对象,直到它 return 删除它 - 这意味着如果异常是抛出到方法内部,那么该方法必须处理该对象 - 这是在创建对象后立即使用 try/catch 完成的。
  • 在您不再需要 Graphics 对象后立即处理它是非常重要的。 System.Drawing 中的一次性类型是原生 Windows GDI 对象的包装器,它会在您的进程中耗尽 GDI 句柄 - 泄漏 GDI 句柄是不好的,因为最终您会 运行-out 然后所有图形操作会突然停止工作(这就是为什么很多写得不好的 WinForms 程序在一段时间后开始出现图形故障的原因)。
  • 此外,img_cropbmp_crop 是变量名的糟糕选择,因为名称没有描述变量是什么,而且匈牙利表示法很糟糕。
    • 在下面的示例中,我对输入图像使用 source,对输出图像使用 cropped

这是我的做法:

public static Bitmap Resize( Bitmap source, int w, int h, int x, int y )
{
    Bitmap resized = new Bitmap( w, h, PixelFormat.Format24bppRgb );
    try
    {
        cropped.SetResolution(80, 60);
        
        using( Graphics g = Graphics.FromImage( cropped ) )
        {
            g.SmoothingMode     = SmoothingMode.AntiAlias;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.PixelOffsetMode   = PixelOffsetMode.HighQuality;
            g.DrawImage( source, new Rectangle( 0, 0, w, h ), x, y, w, h, GraphicsUnit.Pixel );
        }

        // Pass the image to the other class/method/etc:
        Class2( resized );

        return resized; // Return the image to the caller, who now "owns" the image and its their responsibility to dispose of it.
    }
    catch( Exception ex )
    {
        resized.Dispose();
        throw;
    }
}

如果你打算在调用你的Class2方法后returncropped给调用者,那么你应该删除try/catch 而不是使用 using 块,像这样:

public static Bitmap Resize(Bitmap source, int w, int h, int x, int y)
{
    using( Bitmap resized = new Bitmap( w, h, PixelFormat.Format24bppRgb ) )
    {
        cropped.SetResolution(80, 60);
        
        using( Graphics g = Graphics.FromImage( resized ) )
        {
            g.SmoothingMode     = SmoothingMode.AntiAlias;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.PixelOffsetMode   = PixelOffsetMode.HighQuality;
            g.DrawImage( source, new Rectangle( 0, 0, w, h ), x, y, w, h, GraphicsUnit.Pixel );
        }

        // Pass the image to the other class/method/etc:
        Class2( resized );
    }
}