В C # как взаимодействуют инициализаторы полей и инициализаторы объектов? - PullRequest
5 голосов
/ 27 апреля 2011

Я в основном разработчик 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 будет игнорироваться?

Ответы [ 4 ]

5 голосов
/ 24 июня 2013

Я подтверждаю эту ужасную ошибку в Unity3d сборке Mono (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);}
}

На неуниверсальной OSX Mono 2.10.11 (mono-2-10 / 2baeee2 ср. 16 января 16:40:16 EST 2013) тесты работают нормально:

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

РЕДАКТИРОВАТЬ: заполнен баг в трекгере Unity3d: https://fogbugz.unity3d.com/default.asp?548851_3gh8hi55oum1btda

3 голосов
/ 28 апреля 2013

У меня была похожая проблема с Unity & Mono.

Я справился с этим, инициализировав поля в конструкторе, а затем переписав инициализаторами объектов.

ОДНАКО! Сначала это тоже не сработало. Поэтому я заменил поля свойствами со вспомогательными полями, и это, похоже, вызвало ожидаемое поведение.

3 голосов
/ 27 апреля 2011

Самый простой способ увидеть, что происходит, - разбить ваше утверждение на эквивалентное, если оно выполняется построчно.

Оригинал:

PassInFoo( new Foo { Bar = false } );

Разбит:

var tmp = new Foo();    //Bar initialized to true
tmp.Bar = false;
PassInFoo( tmp );
2 голосов
/ 27 апреля 2011
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 отображается в окне консоли).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...