Why a lambda delegate declared as an instance field can only access static members?

225 views Asked by At

I have this:

public class Demo {

    private IService _service;
    
    Action<Guid> action = v => _service.CallServiceWithParameter(v);

}

I get error:

Cannot access non-static field '_service' in static context

huh? Where is the static context and why is a lambda forced to be static? the lambda itself is not static...

2

There are 2 answers

0
Peter B On BEST ANSWER

Field initializers are static statements that are evaluated before the constructor is executed, which is why they can only access other static items.

You can see this if you try to replace the initializer with a method call; it will only compile if you make that method static.

Here is a runnable Demo fiddle: https://dotnetfiddle.net/IVtMHJ

Code from the fiddle:

using System;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Demo is going to be created");
        var d = new Demo();
        Console.WriteLine("Demo has been created");
    }
}

public class Demo
{
    public Demo()
    {
        Console.WriteLine("Running constructor");
    }

    private IService _service;
    
    Action<Guid> action = CreateAction();
    
    public static Action<Guid> CreateAction() // Will get compile error above if we remove "static" here
    {
        Console.WriteLine("Running CreateAction");
        return null;
    }
}

public interface IService { }

Output:

Demo is going to be created
Running CreateAction
Running constructor
Demo has been created

If you move the CreateAction call into the constructor then you can make it non-static:

public Demo()
{
    Console.WriteLine("Running constructor");
    action = CreateAction();
}

private IService _service;

Action<Guid> action;

public Action<Guid> CreateAction() // Now it does not need to be "static"
{
    Console.WriteLine("Running CreateAction");
    return null;
}

Output (from fiddle):

Demo is going to be created
Running constructor
Running CreateAction
Demo has been created

1
Azhari On

Field initializer's cannot reference non-static members. You need to change your _service to be:

private static IService _service;

Or you could move it to the constructor.

public class Demo
{
    private IService _service;
    private Action<Guid> action;

    public Demo(IService service)
    {
        _service = service;
        action = v => _service.CallServiceWithParameter(v);
    }
}