代码之家  ›  专栏  ›  技术社区  ›  jstuardo

编译器正在强制我在“…”上实现终结器或析构函数

  •  0
  • jstuardo  · 技术社区  · 6 年前

    分析VS2017中的代码时,会显示一个错误,告诉您“在“…”上实现终结器或析构函数”。问题是为什么?

    如果我以这种方式实现析构函数:

        ~RawPrinterHelper()
        {
    
        }
    

    显示另一条消息:

    'RawPrinterHelper' implements a finalizer that only calls conditionally emitted methods or the base type finalizer. Remove the finalizer or ensure that it is only conditionally compiled into the assembly. If this violation occurs against a finalizer that is entirely wrapped in a conditionally-emitted block of code, suppress this message. 
    

    如何解决这个问题?该类还实现了IDisposable接口。

    编辑:

    这是生成的完整类:

    public sealed class RawPrinterHelper : IDisposable
    {
        private NativeMethods.DOCINFOA _di = new NativeMethods.DOCINFOA();
        private IntPtr _hPrinter = IntPtr.Zero;
    
        public bool PrinterIsOpened { get; private set; }
    
        public bool OpenPrinter(string printerName)
        {
            if (!this.PrinterIsOpened)
            {
                if (NativeMethods.OpenPrinter(printerName, out _hPrinter, IntPtr.Zero))
                    this.PrinterIsOpened = true;
            }
    
            return this.PrinterIsOpened;
        }
    
        public void ClosePrinter()
        {
            if (this.PrinterIsOpened)
            {
                NativeMethods.ClosePrinter(_hPrinter);
    
                this.PrinterIsOpened = false;
            }
        }
    
        public bool CreateDocument(string name)
        {
            if (this.PrinterIsOpened)
            {
                _di.pDocName = name;
                _di.pDataType = "RAW";
                if (NativeMethods.StartDocPrinter(_hPrinter, 1, _di))
                {
                    if (NativeMethods.StartPagePrinter(_hPrinter))
                    {
                        return true;
                    }
                }
            }
    
            return false;
        }
    
        public void CloseDocument()
        {
            NativeMethods.EndPagePrinter(_hPrinter);
            NativeMethods.EndDocPrinter(_hPrinter);
        }
    
        public bool SendStringToPrinter(string text)
        {
            if (this.PrinterIsOpened)
            {
    
                IntPtr pBytes = Marshal.StringToCoTaskMemAnsi(text);
                int dwCount = text.Length;
                int dwWritten = 0;
    
                try
                {
                    return NativeMethods.WritePrinter(_hPrinter, pBytes, dwCount, out dwWritten);
                }
                finally
                {
                    Marshal.FreeCoTaskMem(pBytes);
                }
            }
    
            return false;
        }
    
        public bool SendBytesToPrinter(byte[] bytes)
        {
            if (this.PrinterIsOpened)
            {
                IntPtr pBytes = Marshal.AllocHGlobal(bytes.Length);
                Marshal.Copy(bytes, 0, pBytes, bytes.Length);
                int dwCount = bytes.Length;
                int dwWritten = 0;
    
                try
                {
                    return NativeMethods.WritePrinter(_hPrinter, pBytes, dwCount, out dwWritten);
                }
                finally
                {
                    Marshal.FreeHGlobal(pBytes);
                }
            }
    
            return false;
        }
    
        public byte[] ReceiveBytesFromPrinter()
        {
            if (this.PrinterIsOpened)
            {
                int maxRead = 256;
                byte[] bytes = new byte[256];
                IntPtr pBytes = Marshal.AllocHGlobal(bytes.Length);
    
                int nBytesRead = 0;
    
                try
                {
                    //Read Data                
                    if (NativeMethods.ReadPrinter(_hPrinter, pBytes, maxRead, out nBytesRead))
                        return bytes;
                }
                finally
                {
                    Marshal.FreeHGlobal(pBytes);
                }
            }
    
            return null;
        }
    
        // SendBytesToPrinter()
        // When the function is given a printer name and an unmanaged array
        // of bytes, the function sends those bytes to the print queue.
        // Returns true on success, false on failure.
        public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
        {
            Int32 dwError = 0, dwWritten = 0;
            IntPtr hPrinter = new IntPtr(0);
            NativeMethods.DOCINFOA di = new NativeMethods.DOCINFOA();
            bool bSuccess = false; // Assume failure unless you specifically succeed.
    
            di.pDocName = "RAW Document";
            // Win7
            di.pDataType = "RAW";
    
            // Win8+
            // di.pDataType = "XPS_PASS";
    
            // Open the printer.
            if (NativeMethods.OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
            {
                // Start a document.
                if (NativeMethods.StartDocPrinter(hPrinter, 1, di))
                {
                    // Start a page.
                    if (NativeMethods.StartPagePrinter(hPrinter))
                    {
                        // Write your bytes.
                        bSuccess = NativeMethods.WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                        NativeMethods.EndPagePrinter(hPrinter);
                    }
                    NativeMethods.EndDocPrinter(hPrinter);
                }
                NativeMethods.ClosePrinter(hPrinter);
            }
            // If you did not succeed, GetLastError may give more information
            // about why not.
            if (bSuccess == false)
            {
                dwError = Marshal.GetLastWin32Error();
            }
            return bSuccess;
        }
    
        public static bool SendFileToPrinter(string szPrinterName, string szFileName)
        {
            // Open the file.
            FileStream fs = new FileStream(szFileName, FileMode.Open);
            // Create a BinaryReader on the file.
            BinaryReader br = new BinaryReader(fs);
            // Dim an array of bytes big enough to hold the file's contents.
            Byte[] bytes = new Byte[fs.Length];
            bool bSuccess = false;
            // Your unmanaged pointer.
            IntPtr pUnmanagedBytes = new IntPtr(0);
            int nLength;
    
            nLength = Convert.ToInt32(fs.Length);
            // Read the contents of the file into the array.
            bytes = br.ReadBytes(nLength);
            // Allocate some unmanaged memory for those bytes.
            pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
            // Copy the managed byte array into the unmanaged array.
            Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
            // Send the unmanaged bytes to the printer.
            bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
            // Free the unmanaged memory that you allocated earlier.
            Marshal.FreeCoTaskMem(pUnmanagedBytes);
            fs.Close();
            fs = null;
            return bSuccess;
        }
        public static bool SendStringToPrinter(string szPrinterName, string szString)
        {
            IntPtr pBytes;
            Int32 dwCount;
            // How many characters are in the string?
            dwCount = szString.Length;
            // Assume that the printer is expecting ANSI text, and then convert
            // the string to ANSI text.
            pBytes = Marshal.StringToCoTaskMemAnsi(szString);
            // Send the converted ANSI string to the printer.
            SendBytesToPrinter(szPrinterName, pBytes, dwCount);
            Marshal.FreeCoTaskMem(pBytes);
            return true;
        }
    
        public void Dispose()
        {
    
        }
    
        ~RawPrinterHelper()
        {
            Dispose();
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   Yennefer    6 年前

    需要终结器来释放非托管资源。通常不需要实现终结器,除非您持有非托管资源。

    终结器为空,这会导致问题:终结器是一个特定的方法,编译器希望您做一些有意义的事情并遵守规范(即必须真正释放非托管资源)。空终结器是编译器的红旗,因为您可能忘记实现它。由于我们处理的是无法自动释放的资源,在这种情况下编译器是非常安全的。

    如果你的类实现 IDisposable ,您可以实现 IDisposable公司 此处描述的模式 MSDN .