Angular case in using lambdas expression in base constructor

In the framework of the Framework we are creating, we need the following template:

public class BaseRenderer { Func<string> renderer; public BaseRenderer(Func<string> renderer) { this.renderer = renderer; } public string Render() { return renderer(); } } public class NameRenderer : BaseRenderer { public string Name{ get; set; } public NameRenderer () : base(() =>this.Name) {} } 

As you can see, we create a lambda when the base constructor is called.

 public class Program { public static void Main() { Console.WriteLine(new NameRenderer(){Name = "Foo"}.Render()); } } 

Oddly enough, when trying to actually use a lambda, it throws a NullReferenceException (console application) or some kind of ExceptionEngineExceptionexception (web application in IIS).

I think the reason is that this pointer is not ready before calling the base constructor, so the lambda cannot capture this.Name at this point.

Shouldn't an exception be thrown at capture time instead of run time? Is this behavior described?

I can reorganize the code differently, but I think it is worth the comment.

+6
c # lambda linq
Dec 09 '09 at 18:46
source share
5 answers

As asgerhallas is correctly indicated, this should not be legal in accordance with the specification. We accidentally allowed this dummy use to infiltrate an error detector that is looking for the wrong ways to use "this" before it is legal. I fixed the error; C # 4 compiler correctly puts your program as an error.

Many apologies for the inconvenience; that was my fault.

+22
Dec 09 '09 at 19:33
source share

The C # specification in 7.5.7 says: "This access is permitted only in the instance constructor, instance method, or instance instance block."

And even more directly in 10.11.1: β€œThe instance constructor initializer cannot access the instance being created. Therefore, it is a compile-time error to refer to this in the constructor initializer argument expression, how this compiles is a temporary error for the argument expression to refer to any instance member through a simple name. "

Although the instance was created in accordance with 7.5.10.

Hm. This is actually quite strange. I did not see a compile-time error.

+6
Dec 09 '09 at 19:05
source share

I think you're right. A subclass is not yet constructed when the constructor of the base class is called, and therefore accessing the elements in the subclass gives you a null reference. The CLR cannot know at compile time if an instance exists or not.

Moving logic to the constructor body should fix the problem.

+4
Dec 09 '09 at 19:01
source share

The lambda fixed the value of "this" and fixed the value null, since the object has not yet been constructed. This strikes me as a compiler error, for this an error should have occurred. Similar code is usually generated by CS0027 (the keyword 'this' is not available in the current context) or CS0120 (an object reference is required). I bet it’s not easy to implement.

Anyhoo, the code cannot work. The NameRenderer class needs a constructor with a string argument so that it can initialize the base class.

+2
Dec 09 '09 at 19:34
source share

won't : base(()=>this) legal? You can do : this() , so the link to this seems fine, there are simply no properties on it. The fact that : base(()=>this) no longer legal just violated some of the partial functions that I used during construction. You can fix it by moving it to the constructor body, but there is a difference in the orders: the base class can no longer be transparently passed by the application of the partial function to itself (because the base class constructor is called before the body of the subclass constructor).

+1
Dec 14 '10 at 4:19
source share



All Articles