2011-04-27 9 views
5

私は主にC++開発者ですが、最近はC#でプロジェクトを進めています。今日私は、オブジェクトイニシャライザを使用している間、少なくとも私には予期せぬ動作を経験しました。私はここにいる誰かが何が起こっているのかを説明できることを願っています。私が期待するようC#では、フィールドイニシャライザとオブジェクトイニシャライザはどのように相互作用しますか?

例A

public class Foo { 
    public bool Bar = false; 
} 

PassInFoo(new Foo { Bar = true }); 

例B

public class Foo { 
    public bool Bar = true; 
} 

PassInFoo(new Foo { Bar = false }); 

例Aで動作します。 PassInFooに渡されたオブジェクトには、Barがtrueに設定されています。ただし、例Bでは、foo.Barがtrueに設定されていますが、オブジェクト初期化子でfalseが割り当てられています。例Bのオブジェクトイニシャライザが一見無視される原因は何ですか?

+6

何もありません。あなたはあなたが見ていると思っているものを見ていません。 – mquander

+3

これを再現することはできません.Net 3.5では、どのバージョンがありますか、これはあなたが見ている動作ですか? –

+2

コンストラクタは、オブジェクト初期化子とフィールド初期化子がコンストラクタの一部である前に実行されます。 C#仕様:7.6以降を参照してください。10- オブジェクトイニシャライザまたはコレクションイニシャライザを含むオブジェクト作成式の処理は、まずインスタンスコンストラクタを処理した後、オブジェクトイニシャライザ(§7.6.10.2)またはコレクションイニシャライザ(§7.6)で指定されたメンバまたは要素の初期化を処理することから成ります。 10.3)。 – VinayC

答えて

3

何が起こっているのかを確認する最も簡単な方法は、行ごとに行えば、文を等価にすることです。

オリジナル:

PassInFoo(new Foo { Bar = false }); 

勃発:Framework 3.5の(偽のコンソールウィンドウに表示されている)を用いて検証するとき

var tmp = new Foo(); //Bar initialized to true 
tmp.Bar = false; 
PassInFoo(tmp); 
+0

Btw、私は上記の.NET 3.5と4.0をテストしましたが、どちらの場合もBarは実際には 'PassInFoo'の中ではfalseです。 – Thomas

+0

私はこれをUnity3Dプロジェクトで試してみましたが、正しく動作しました。 UnityまたはMonoDevelopは、代入が型のデフォルト値(例のコードではboolの場合はfalse)の場合、オブジェクトの初期化子代入を無視するいくつかの「最適化」を行わなければなりません。もっと具体的な答えを出すために、おそらくこの質問をコミュニティに持たなければならないでしょう。 – nschrag

+2

@nschrag - これらの環境の1つが評価の順序を乱していたことを知ることは非常に邪魔になります。がんばろう! – Thomas

2
class Program 
{ 
    static void Main(string[] args) 
    { 
     PassInFoo(new Foo { Bar = false }); 
    } 
    public class Foo 
    { 
     public bool Bar = true; 
    } 

    public static void PassInFoo(Foo obj) 

    { 
     Console.WriteLine(obj.Bar.ToString()); 
     Console.ReadLine(); 
    } 
} 

上記のコードは正常に動作しています。

3

Unityと同様の問題がありました。& Mono。

私はコンストラクタのフィールドを初期化し、オブジェクト初期化子で上書きしています。

どのように!最初はこれもうまくいかなかった。だから私は、フィールドをバッキングフィールドでプロパティに置き換え、予想される動作を強制するように見えました。

5

MonoのUnity3dビルド(Mono 2.6.5、Unity3d 4.1.2f1、OSX)でこの醜いバグを確認します。

それはあなたがint != 0を渡すことができますので、ValueTypeにはデフォルト値を使用するようにしないようになど(bool)true、うまく見えるが、(int)0または(bool)falseのようなデフォルト値を渡すと、それは価値だ無視します。

証明:非unity3d OSXモノ2.10.11(モノ2-10/2baeee2水1月16日夜04時40分16秒EST 2013)に

using UnityEngine; 
using System.Collections; 

public class Foo1 { 
    public bool Bar=false; 
} 

public class Foo2 { 
    public bool Bar=true; 
} 

public class Foo1i { 
    public int Bar=0; 
} 

public class Foo2i { 
    public int Bar=42; 
} 

public class PropTest:MonoBehaviour { 

    void Start() { 
     PassInFoo(new Foo1 {Bar=true}); // FOO1: True (OK) 
     PassInFoo(new Foo2 {Bar=false});/// FOO2: True (FAIL!) 
     PassInFoo(new Foo1i {Bar=42}); // FOO1i: 42 (OK) 
     PassInFoo(new Foo2i {Bar=0});/// FOO2i: 42 (FAIL!) 
     PassInFoo(new Foo2i {Bar=13});/// FOO2i: 13 (OK) 
    } 

    void PassInFoo(Foo1 f) {Debug.Log("FOO1: "+f.Bar);} 

    void PassInFoo(Foo2 f) {Debug.Log("FOO2: "+f.Bar);} 

    void PassInFoo(Foo1i f) {Debug.Log("FOO1i: "+f.Bar);} 

    void PassInFoo(Foo2i f) {Debug.Log("FOO2i: "+f.Bar);} 
} 

テストが細かい実行されている:

FOO1: True 
FOO2: False 
FOO1i: 42 
FOO2i: 0 
FOO2i: 13 

EDIT:unity3dのバグトラッカーにバグでいっぱい:https://fogbugz.unity3d.com/default.asp?548851_3gh8hi55oum1btda

+1

Unity 5(エディタのみ)にチェックされています。このバグはまだ残っています。ハッピーデバッグ。 –

+1

Unity QAからメッセージが届きました。今後のリリースで不具合が修正されます。 –

+0

印象的なもの、@ChanibaL – Fattie