2

Inside a MVC controller I attempted to create a field similar to:

Func<MyModel, ViewResult> ModelResult=(model) => View("myview.cshtml", model);

This results in the compilation error

An object reference is required for the non-static field, method, or property 'System.Web.Mvc.Controller.View(string, object)'

This code works fine as a method

private ViewResult ModelResult(MyModel model)
{
    return View("myview.cshtml", model);
}

It also works fine if the field is initialized by the constructor

public MyController()
{
    ModelResult=(model) => View("myview.cshtml", model);
}

Why is the field initializer treated as a static context?

jruizaranguren
  • 12,679
  • 7
  • 55
  • 73
Chris Marisic
  • 32,487
  • 24
  • 164
  • 258
  • Good question, it's strange why lambda with call to instance method is not allowed in field initialization. I guess you could find help [here](http://stackoverflow.com/a/17030381/1283124) – Ilya Ivanov Oct 17 '14 at 21:01
  • possible duplicate of [Why C# lamba expression can't use instance properties and fields?](http://stackoverflow.com/questions/17030351/why-c-sharp-lamba-expression-cant-use-instance-properties-and-fields) – Andrew Whitaker Oct 17 '14 at 21:05

1 Answers1

3

Field initializers run before constructors, in the reverse order of constructors. That is, they run from the most derived type up to the least derived type, and the least derived type's fields will be initialized before any of the constructors are called. A design decision was made not to allow this to be referenced before the base type's constructor has been called, or perhaps, more generally, not to allow references to a partially constructed instance from a field initializer.

I think it's a sensible decision. If you are not intimately familiar with the language, the state of the object when a field initializer runs is less clear than when a constructor runs. The way in which a constructor declaration flows reflects the actual order in which constructors are called, so it's easier to reason about the state. Specifically, the : base() call appears before the constructor body, implying the base constructor has already run by the time you enter the body. You cannot infer the object's state as easily at a field declaration site, and in fact the field initialization order differs from Java, which was arguably the most similar mainstream language when C# was introduced.

Mike Strobel
  • 25,075
  • 57
  • 69