Search code examples
c#staticfieldinitializernon-static

A field initializer cannot reference the non-static field, method, or property


I have the following code into a Form:

using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Media;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ScreenShots
{
    public partial class ScreenShotConfigurationForm : Form
    {

        // ----- some other stuff (code, methods, etc...) is placed in here -----

        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private LowLevelKeyboardProc _proc = HookCallback; // <<<< This is the row that is causing the error
        private IntPtr _hookID = IntPtr.Zero;

        private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                if (vkCode == 44) // 44 is the key code of PrintScreen button
                {
                    MakeScreenShot();
                }
            }

            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        private IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())

            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]

        private extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private extern IntPtr GetModuleHandle(string lpModuleName);
    }
}

That is giving me the following error on Microsoft C# 2008:

A field initializer cannot reference the non-static field, method, or property 'ScreenShots.ScreenShotConfigurationForm.HookCallback(int, System.IntPtr, System.IntPtr)'

  1. What does it mean?
  2. How can I solve it?

A screenshot of what I see: enter image description here


Solution

  • What does it mean?

    The error said:

    A field initializer

    It's referring to the field private LowLevelKeyboardProc _proc. It's a non-static field. The initializer part is = HookCallback;.

    cannot reference the non-static field, method, or property 'HookCallback'

    HookCallback is a non-static method, and the field initializer is obviously referring to it.

    The thing that is forbidden here is instance members being initialized with other instance members. Since they are all initialized "at the same time" - when the instance is created - they should not refer to each other when being initialized.

    It's something that the C# compiler could actually figure out in theory - the spec defines a specific order in which initializers run - but for whatever reason, the designers went with the error message instead.

    How do you fix it?

    It's only field initializers which aren't allowed to access instance members. You can access instance members in the constructor, which runs right after the field initializers. So, just move the initialization to your constructor (as recommended by Microsoft):

    private LowLevelKeyboardProc _proc;
    
    public ScreenShotConfigurationForm()
    {
        InitializeComponent();
        _proc = HookCallback;
    }