Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Non-static class method can be added to Dictionary but not with collection initializer

The following code creates a dictionary with Actions.

class Test
{
    private Dictionary<string, Action> ActionLookup = new();

    public Test()
    {
        ActionLookup.Add("key", SampleAction);
    }

    protected virtual void SampleAction()
    {
        // Do something useful here...
    }
}

That code works. However, the following version gives me a compile error.

class Test
{
    private Dictionary<string, Action> ActionLookup = new()
    {
        ["key"] = SampleAction  // ERROR CS0236
    };

    protected virtual void SampleAction()
    {
        // Do something useful here...
    }
}

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Why can’t I add SampleAction to my dictionary using a collection initializer when it’s perfectly valid to add it manually?

I know I can workaround it using something like the following, but why is this necessary?

class Test
{
    private Dictionary<string, Action<MyClass>> ActionLookup = new()
    {
        ["key"] = o => o.SampleAction()
    };

    protected virtual void SampleAction()
    {
        // Do something useful here...
    }
}

Note: It’s not an option to make SampleAction static because I need it to be virtual.

>Solution :

This is happening because the context you are accessing the SampleAction changes. In the first code it is an instance method, in the second code it’s field initializer.

There is one simple workaround which is turning ActionLookup into a property by using expression bodies (notice the => instead of =):

private Dictionary<string, Action> ActionLookup => new()
{
    ["key"] = SampleAction  // ERROR CS0236
};

But, this will create the dictionary every time you access the property.

You can fix it by using a backing field for it:

private Dictionary<string, Action> _actionLookup;

private Dictionary<string, Action> ActionLookup
{
     get
     {
          if (_actionLookup != null)
          {
              _actionLookup = new Dictionary<string, Action>() { ["key"] = SampleAction };
          }

          return _actionLookup;
     }
}

I know a lot of workarounds going on here and your workaround may be simpler than this, but it’s just another way to make it work. But I don’t think it is worth just to get a simpler syntax.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading