1

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

Michael Wiles
  • 20,902
  • 18
  • 71
  • 101
  • Does this answer your question? [c# Methods error CS0236](https://stackoverflow.com/questions/43211580/c-sharp-methods-error-cs0236) and [CS0236 A field initializer cannot reference the non-static field, method, or property 'corona.line'](https://stackoverflow.com/questions/60639734/) –  Aug 24 '21 at 09:21
  • I just get CS0236, as Olivier says, and that error doesn't specify "in static context" so I'm curious what specific error you're getting here. – Damien_The_Unbeliever Aug 24 '21 at 09:33
  • I do think it's a bit of an overreach of the rule as the lambda is not actually _run_ at the point of definition. It is just created. And I'd have thought that to define the lambda: action you don't actually have to _run_ the lambda... – Michael Wiles Aug 25 '21 at 07:29

2 Answers2

3

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);
    }
}
Azhari
  • 535
  • 5
  • 20
  • 2
    Huh? But why does this rule also apply inside the lambda? Defining the lambda does not include running it - when it runs its not going to run in static context. Why does defining the lambda also include the actual content of the lambda? – Michael Wiles Aug 24 '21 at 16:52
3

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

Peter B
  • 22,460
  • 5
  • 32
  • 69