C# 在基构造函数中使用lambdas表达式时的角点大小写

C# 在基构造函数中使用lambdas表达式时的角点大小写,c#,linq,c#-3.0,lambda,C#,Linq,C# 3.0,Lambda,在我们正在构建的框架中,我们需要以下模式: public class BaseRenderer { Func<string> renderer; public BaseRenderer(Func<string> renderer) { this.renderer = renderer; } public string Render() { return renderer(); } }

在我们正在构建的框架中,我们需要以下模式:

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)
     {}
}
奇怪的是,当尝试实际使用lambda时,它会抛出NullReferenceException(控制台应用程序)或某种ExecutionEngineeExceptionException(IIS上的Web应用程序)

我认为原因是这个指针在调用基本构造函数之前还没有准备好,所以lambda在此阶段无法捕获
this.Name

它不应该在“捕获时间”而不是“执行时间”中抛出异常吗? 这种行为有记录吗


我可以用不同的方式重构代码,但我认为值得一提

我认为你是对的。当调用基类构造函数时,子类尚未构造,因此访问子类上的成员会给您一个空引用。CLR无法在编译时知道实例是否存在

将逻辑移到构造函数体应该可以解决问题。

7.5.7中的C#规范说:“只有在实例构造函数、实例方法或实例访问器的块中才允许此访问。”

在10.11.1中更直接地说:“实例构造函数初始值设定项无法访问正在创建的实例。因此,在构造函数初始值设定项的参数表达式中引用此项是编译时错误,参数表达式通过简单名称引用任何实例成员也是编译时错误。”

虽然该实例是根据7.5.10创建的


嗯,这真的很奇怪。我没有看到任何编译时错误。

正如asgerhallas正确指出的那样,根据规范,这不应该是合法的。我们意外地允许错误检测器在合法之前搜索“this”的错误用法,从而使这种虚假用法潜行。我已经修复了错误;C#4编译器正确地将您的程序标记为错误


对给您带来的不便深表歉意;这是我的错误。

lambda捕获了“this”的值,并捕获了null,因为对象尚未构造。我觉得这是一个编译器错误,它应该为此生成一个错误。这样的代码通常会生成CS0027(关键字“this”在当前上下文中不可用)或CS0120(需要对象引用)。我打赌这不容易实现


无论如何,代码不能工作。NameRenderer类需要一个带字符串参数的构造函数,这样它就可以初始化基类。

基类(()=>这个)是否合法?您可以执行以下操作:
:this()
,因此对它的引用似乎很好,而不是它的属性。
:base(()=>this)
不再合法这一事实打破了我在构建过程中所做的一些部分函数应用程序。可以通过将基类移动到构造函数体中来修复,但顺序不同:基类不能再透明地将部分函数应用程序传递给它自己(因为基类构造函数在子类构造函数体之前被调用)

我第一次不太对。当时有一个实例,但您无法访问它。答案已更新。您没有看到编译错误,因为编译器有错误。这应该是一个错误,在C#4中也是。这是以前问过的,它将在C#4.0hah中得到修复,a)你在编译器中遇到错误,b)负责开发的人对你的问题做出了轻微的回答:-P太好了!
public class Program
{
    public static void Main()
    {
        Console.WriteLine(new NameRenderer(){Name = "Foo"}.Render());
    }
}