簡體   English   中英

在C#中,字段初始化器和對象初始化器如何交互?

[英]In C#, how do field initializers and object initializers interact?

我主要是一名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中,盡管在對象初始值設定項中賦值為false,但foo.Bar設置為true。 什么會導致示例B中的對象初始化程序看似被忽略?

我在Unity的Unity3d版本(Mono 2.6.5,Unity3d 4.1.2f1,OSX)中確認了這個丑陋的錯誤。

看起來它不喜歡使用ValueType的默認值,所以你可以傳遞一個int != 0(bool)true等等,但傳遞默認值如(int)0(bool)false忽略了它的價值。

證明:

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);}
}

在非unity3d OSX Mono 2.10.11(單聲道2-10 / 2baeee2 Wed Jan 16 16:40:16 2013)上,測試運行良好:

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

編輯:填寫了unity3d的bugtracker中的一個錯誤: https ://fogbugz.unity3d.com/default.asp?548851_3gh8hi55oum1btda

我和Unity&Mono有類似的問題。

我通過初始化構造函數中的字段然后用對象初始化器覆蓋來解決它。

但是! 起初這也不起作用。 所以我用帶有支持字段的屬性替換了字段,它似乎強制了預期的行為。

查看正在發生的事情的最簡單方法是,如果逐行完成,則將您的語句分解為等效語句。

原版的:

PassInFoo( new Foo { Bar = false } );

爆發:

var tmp = new Foo();    //Bar initialized to true
tmp.Bar = false;
PassInFoo( tmp );
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();
    }
}

使用Framework 3.5驗證時,上面的代碼工作正常(控制台窗口顯示false)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM