16

このコードは正常にコンパイルされますが、コンパイルに失敗するはずです。また、実行するとNullReferenceException. 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" }
                      };
    }
}

これは既知のバグですか?

4

7 に答える 7

41

なぜコンパイルに失敗すると思いますか? これはネストされたオブジェクト初期化構文であり、初期化に有効な値を提供するのはクライアント コードの役割です。

ドキュメントから:

C# 仕様 7.5.10.2「オブジェクト初期化子」

等号の後にオブジェクト初期化子を指定するメンバー初期化子は、ネストされたオブジェクト初期化子、つまり埋め込みオブジェクトの初期化です。フィールドまたはプロパティに新しい値を割り当てる代わりに、ネストされたオブジェクト初期化子での割り当ては、フィールドまたはプロパティのメンバーへの割り当てとして扱われます。

于 2010-10-01T14:23:06.923 に答える
16

いいえ、これはバグではありません。

実行したい場合は、new前に置くかBar(初期化子の前に Foo で行ったように)、または Foo のコンストラクターで Bar オブジェクトを作成します。

オブジェクト初期化子は、基本的に単なるシンタックス シュガーです。

これ:

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

これとまったく同じです:

var foo = new Foo();
foo.Bar.Name = "Hello"; 
于 2010-10-01T14:26:17.650 に答える
3

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

最も重要なのは最後の1つです。構文の右側を表しproperty = valueます。これは、右側が通常の c# 式 (new演算子を使用)または別の初期化子である可能性があることを意味します。その場合、必要なのは左中括弧と右中括弧だけです。

于 2010-10-01T14:24:18.170 に答える
2
...
 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"}
  };
 }
}
于 2010-10-01T14:47:46.257 に答える
2

コードを次の同等のものに変更すると、コンパイル時のエラー/警告ではなく、NullReferenceException の実行時エラーも発生します。

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

結果は同じで、Bar は適切に初期化されません。現在、コンパイラ作成者の観点からは、Bar が使用前に適切に初期化されているかどうかをすべてのケースで判断することは非常に困難です。

于 2010-10-01T14:33:47.397 に答える
1

BarのプロパティでFooあるため、コンパイル時にアクセスして名前プロパティを割り当てることができますが、実行時にBar存在しない有効なインスタンスをチェックするため、null 参照例外がスローされます。 C# バージョン。

于 2010-10-01T14:25:04.780 に答える
0

作業サンプルを作成します。

簡単です。「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();
    }
}
于 2010-10-05T12:02:13.740 に答える