这是 C# 4.0 编译器中的错误吗?

发布于 2024-09-25 13:46:57 字数 451 浏览 6 评论 0原文

这段代码编译成功,但我认为它应该编译失败。此外,当您运行它时,您会收到一个 NullReferenceException 异常。缺少的代码是 Bar 属性初始化中的“new Bar”。

class Bar
{
    public string Name { get; set; }
}

class Foo
{
    public Bar Bar { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        var foo = new Foo
                      {
                          Bar = { Name = "Hello" }
                      };
    }
}

这是一个已知的错误吗?

This code compiles successfully, but I think it should fail to compile. Also, when you run it you get a NullReferenceException. The missing code is the "new Bar" in the initialization of the Bar property.

class Bar
{
    public string Name { get; set; }
}

class Foo
{
    public Bar Bar { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        var foo = new Foo
                      {
                          Bar = { Name = "Hello" }
                      };
    }
}

Is this a known bug?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

莫相离 2024-10-02 13:46:57

为什么你认为它应该无法编译?它是嵌套对象初始值设定项语法,客户端代码负责为初始化提供有效值。

来自文档:

C# 规范 7.5.10.2“对象初始值设定项”

在等号后指定对象初始值设定项的成员初始值设定项是嵌套对象初始值设定项,即嵌入对象的初始化。嵌套对象初始值设定项中的赋值被视为对字段或属性的成员的赋值,而不是向字段或属性赋值新值

Why do you think it should fail to compile? It is nested object initializer syntax, and it is the responsibility of the client code to provide a valid value for initialization.

From the documentation:

C# spec 7.5.10.2 "Object initializers"

A member initializer that specifies an object initializer after the equals sign is a nested object initializer, i.e. an initialization of an embedded object. Instead of assigning a new value to the field or property, the assignments in the nested object initializer are treated as assignments to members of the field or property

木有鱼丸 2024-10-02 13:46:57

不,这不是一个错误。

如果您希望它运行,您可以在 Bar 之前放置一个 new (就像您在初始化程序之前对 Foo 所做的那样),或者在 Foo 的构造函数中创建 Bar 对象。

对象初始值设定项本质上只是语法糖。

这:

var foo = new Foo
            {
                Bar = { Name = "Hello" }
            };

与此完全相同:

var foo = new Foo();
foo.Bar.Name = "Hello"; 

No this is not a bug.

If you want it to run you either put a new before Bar (just like you did for Foo before the initializer) or you create the Bar object in Foo's constructor.

The object initializer is essentially just syntactic sugar.

This:

var foo = new Foo
            {
                Bar = { Name = "Hello" }
            };

Is exactly the same as this:

var foo = new Foo();
foo.Bar.Name = "Hello"; 
独守阴晴ぅ圆缺 2024-10-02 13:46:57

new 在对象初始值设定项中是不必要的:

object-creation-expression:
    new   type   (   argument-list(opt)   )   object-or-collection-initializer(opt) 
    new   type   object-or-collection-initializer

object-or-collection-initializer:
    object-initializer
    collection-initializer

object-initializer:
    {   member-initializer-list(opt)   }
    {   member-initializer-list   ,   }

initializer-value:
    expression
    object-or-collection-initializer

最后一个是最重要的。它代表 property = value 语法的右侧。这意味着右侧可以是普通的 C# 表达式(带有 new 运算符)另一个初始化器。在这种情况下,您所需要的只是左大括号和右大括号。

The new is unecessary in an object initializer:

object-creation-expression:
    new   type   (   argument-list(opt)   )   object-or-collection-initializer(opt) 
    new   type   object-or-collection-initializer

object-or-collection-initializer:
    object-initializer
    collection-initializer

object-initializer:
    {   member-initializer-list(opt)   }
    {   member-initializer-list   ,   }

initializer-value:
    expression
    object-or-collection-initializer

It's that last one that is most important. It represents the right-hand-side of your property = value syntax. This means that the right-hand-side can be a normal c# expression (with a new operator) or another initalizer. In which case, all you need are the opening and closing braces.

私藏温柔 2024-10-02 13:46:57

如果将代码更改为以下等效代码,您还将收到 NullReferenceException 的运行时错误,而不是编译时错误/警告。

static void Main(string[] args) {
    Foo foo2 = new Foo();
    foo2.Bar.Name = "test";
}

效果是一样的,Bar 永远不会被正确初始化。现在,从编译器编写者的角度来看,在所有情况下都很难确定 Bar 在使用之前是否已正确初始化。

If you change your code to the following equivalent, you will also get a runtime error of a NullReferenceException instead of a compile time error/warning.

static void Main(string[] args) {
    Foo foo2 = new Foo();
    foo2.Bar.Name = "test";
}

The effect is the same, Bar is never properly initialized. Now, from a compiler writers perspective it is extremely difficult to determine in all cases as to whether Bar was properly initialized prior to use.

Hello爱情风 2024-10-02 13:46:57
...
 Bar = { Name = "Hello"}
...

意思是: Foo.Bar.Name="Hello"
不是: {Foo.Bar=new Bar(); Foo.Bar.Name="Hello";}

这将编译并且不会抛出任何异常,因此这不是一个错误,您只是初始化一个不存在的对象:

class Bar
{
    public string Name;
}
class Foo
{
private Bar _bar = new Bar();
public Bar Bar
{
  get { return _bar; }
  set { _bar = value; }
}
}
class Program
{
 static void Main(string[] args)
 {
  Foo foo = new Foo
  {
   Bar = { Name = "Hello"}
  };
 }
}
...
 Bar = { Name = "Hello"}
...

means: Foo.Bar.Name="Hello"
not: {Foo.Bar=new Bar(); Foo.Bar.Name="Hello";}

This will compile and will not throw any exception, so it's not a bug, you're just initializing an unexisting object:

class Bar
{
    public string Name;
}
class Foo
{
private Bar _bar = new Bar();
public Bar Bar
{
  get { return _bar; }
  set { _bar = value; }
}
}
class Program
{
 static void Main(string[] args)
 {
  Foo foo = new Foo
  {
   Bar = { Name = "Hello"}
  };
 }
}
送舟行 2024-10-02 13:46:57

BarFoo 的一个属性,因此它允许您在编译时访问它并分配一个 name 属性,但在运行时它会检查 的有效实例code>Bar 不存在,因此会抛出空引用异常,任何 C# 版本都会出现这种情况。

Bar is a property of Foo, so it is allowing you to access it and assigning a name property at compile time, but at run time it checks for the valid instance of Bar which is not present so throwing null reference exception, it will be the case with any C# version.

_失温 2024-10-02 13:46:57

我创建了一个工作示例

很简单,只需添加一个“new Bar()”即可正常工作


class Bar
{
    public string Name { get; set; }
}

class Foo
{
    public Bar Bar { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        var foo = new Foo
                      {
                          Bar = new Bar() { Name = "Hello" }
                      };

        Console.WriteLine(foo.Bar.Name);
        Console.ReadLine();
    }
}

I create a working sample.

Its easy, only add a "new Bar()" an it work fine


class Bar
{
    public string Name { get; set; }
}

class Foo
{
    public Bar Bar { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        var foo = new Foo
                      {
                          Bar = new Bar() { Name = "Hello" }
                      };

        Console.WriteLine(foo.Bar.Name);
        Console.ReadLine();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文