Компилятор заставляет меня реализовать финализатор или деструктор в «...» - PullRequest
0 голосов
/ 15 января 2019

при анализе кода в VS 2017 появляется сообщение об ошибке «Внедрить финализатор или деструктор в« ... »». Вопрос почему?

Если я реализую деструктор так:

    ~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.

EDIT:

Это полный класс:

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 Ответ

0 голосов
/ 15 января 2019

Финализатор необходим для удаления неуправляемых ресурсов.Обычно вам не нужно реализовывать финализатор, если у вас нет неуправляемых ресурсов.

Ваш финализатор пуст, и это вызывает проблему: финализатор - это особый метод, и компилятор хочет, чтобы вы делали что-то осмысленное и придерживающеесяспецификациям (т.е. должны действительно освобождать неуправляемые ресурсы).Пустой финализатор - это красный флаг для компилятора, потому что вы могли забыть его реализовать.Поскольку мы имеем дело с ресурсами, которые не могут быть автоматически освобождены, компилятор в этом случае является сверхбезопасным.

Если ваш класс реализует IDisposable, вы можете реализовать шаблон IDisposable, как описано здесь MSDN .

...