在 C# 中,字段初始值设定项和对象初始值设定项如何交互?

发布于 2024-11-03 09:46:42 字数 498 浏览 1 评论 0原文

我主要是一名 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 指定为 false,但 foo.Bar 仍设置为 true。是什么导致示例 B 中的对象初始值设定项看似被忽略?

I'm primarily a C++ developer, but recently I've been working on a project in C#. Today I encountered some behavior that was unexpected, at least to me, while using object initializers. I'm hoping someone here can explain what's going on.

Example A

public class Foo {
    public bool Bar = false;
}

PassInFoo( new Foo { Bar = true } );

Example B

public class Foo {
    public bool Bar = true;
}

PassInFoo( new Foo { Bar = false } );

Example A works as I'd expect. The object passed into PassInFoo has Bar set to true. However, in Example B, foo.Bar is set to true, despite being assigned false in the object initializer. What would be causing the object initializer in Example B to be seemingly ignored?

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

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

发布评论

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

评论(4

半仙 2024-11-10 09:46:42

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

在非unity3d OSX Mono 2.10.11(mono-2-10/2baeee2 Wed Jan 16 16:40:16 EST 2013)上测试运行良好:

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

编辑:在unity3d的bugtracker中填写了一个错误:https://fogbugz.unity3d.com/default.asp?548851_3gh8hi55oum1btda

I confirm this ugly bug in Unity3d build of Mono (Mono 2.6.5, Unity3d 4.1.2f1, OSX).

It looks like it doesn't like to use the default value for the ValueType, so you can pass a int != 0, (bool)true etc just fine, but passing in the default value like (int)0 or (bool)false ignores it's value.

Proof:

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

On a non-unity3d OSX Mono 2.10.11 (mono-2-10/2baeee2 Wed Jan 16 16:40:16 EST 2013) the tests are running fine:

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

EDIT: filled in a bug in unity3d's bugtracker: https://fogbugz.unity3d.com/default.asp?548851_3gh8hi55oum1btda

善良天后 2024-11-10 09:46:42

查看正在发生的情况的最简单方法是将您的语句分解为等效的语句(如果逐行完成)。

原文:

PassInFoo( new Foo { Bar = false } );

破解:

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

The easiest way to see what is happening is to break out your statement into its equivalent if done line-by-line.

Original:

PassInFoo( new Foo { Bar = false } );

Broken out:

var tmp = new Foo();    //Bar initialized to true
tmp.Bar = false;
PassInFoo( tmp );
只等公子 2024-11-10 09:46:42

我在 Unity & 中遇到了类似的问题。单核细胞增多症。

我通过初始化构造函数中的字段然后用对象初始值设定项覆盖来解决这个问题。

然而 !起初这也不起作用。因此,我用带有支持字段的属性替换了字段,这似乎强制了预期的行为。

I had a similar problem with Unity & Mono.

I got around it by initializing the fields in the constructor and then overwriting with the object initializers.

HOWEVER ! At first this didn't work either. So I replaced the fields with properties with backing fields and it seemed to force expected behaviour.

虚拟世界 2024-11-10 09:46:42
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)。

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

The above code is working fine when verified with Framework 3.5 (false is displayed on the console window).

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