![](/img/trans.png)
[英]Strange (possibly wrong?) C# compiler behavior with method overloading and enums
[英]Strange behavior with C# enums
我在这里开发游戏,发现这个有趣的错误。 假设你有这个枚举:
public enum ItemType
{
Food,
Weapon,
Tools,
Written,
Misc
};
一个基类
public class BaseItem
{
public string Name = "Default Name";
public ItemType Type = ItemType.Misc;
}
以及它的两个实例:
Ins1 = new BaseItem
{
Name = "Something",
Type = ItemType.Food
};
Ins2 = new BaseItem
{
Name = "Something too",
Type = ItemType.Tools
}
这就是我发生的事情:第一个实例的类型将保留为基类中的预初始化,即使我在其构造函数中指定我希望类型为Food。 第二个实例的类型将正确设置为工具。
如果,我在食物之前添加了一个新的枚举值,例如:
public enum ItemType
{
Nothing,
Food,
Weapon,
Tools,
Written,
Misc
};
那么第一个实例的类型就像预期的那样,食物。 第二个实例的类型也是正确的。
什么可能导致这种行为? 简而言之,所有其类型已在构造函数中设置为枚举的第一个值的实例实际上将返回到它们在BaseItem定义中具有的值。 在第一个枚举值之前添加额外的值可以解决问题,显然; 但这是错的,所以我想知道可能导致这个问题的原因。
谢谢!
---稍后编辑---如果这有帮助:不对BaseItem内的“Type”字段进行任何初始化,只留下大括号构造函数进行初始化,一切正常,而不向枚举添加“Nothing”值。
为此事道歉; 经过一些挖掘,似乎它只是一个Unity的bug。 其他一些人也遇到过它。 我解决了这个问题; 每个人都得到我的投票,我会添加自己的答案; 也许其他一些Unity用户会找到它。 非常感谢您的帮助和兴趣!
如果有其他Unity用户在这里搜索信息,认为这是一些.NET行为问题:它似乎只是一个Unity错误。 其他人也遇到过它。 只是避免在类本身中为这种东西进行任何类型的初始化,或者使用属性。
它绝对不是Microsoft .NET问题,也不是Mono .NET问题(您可以随时使用相同的代码启动Mono项目,并且它将正常工作)。
如果声明您的枚举ItemType
的代码在另一个程序集(项目)中,而不是声明BaseItem
类的代码或引入Ins1
和Ins2
变量的代码,那么在对其进行更改时重新编译所有程序集至关重要。 ItemType
枚举的定义。
只是有个主意。 不确定它是否会起作用。 初始化后,似乎正在调用BaseItem的构造函数。 尝试设置一个断点,看看何时调用BaseItem的构造函数。 或者您可以在设置Name和Type之前尝试显式调用BaseItem的构造函数。
这只是一个猜测,但是,因为Enum的第一个值等于0,可能是在定义中设置默认值(ItemType.Misc或5)的组合,再加上使用将值设置回的类型初始值设定项如果您没有默认值(ItemType.Food或0)会导致您指定的默认值(ItemType.Misc)被保留。
顺便说一句,这很重要,实际上并没有定义构造函数。 语法
Ins1 = new BaseItem
{
Name = "Something",
Type = ItemType.Food
};
...不是对构造函数的调用,而是对类型初始值设定项的调用。 是的,默认构造函数被调用,但在该构造函数中没有任何反应。
我打赌,如果你真的使用构造函数并在那里设置ItemType的默认值,你会发现这个问题消失了。 就像是:
public BaseItem()
{
this.Type = ItemType.Misc;
}
虽然我不记得阅读任何明确说明这一点的内容,但我觉得您不应该使用您使用的语法为公共属性或字段设置默认值。 如果需要设置,请在构造函数中设置它,以便可以轻松覆盖它。 您使用的语法更适合私有支持字段,而不是可以从类外部设置的内容。
这段代码应该可以正常工作 也许你应该尝试发布一个重现问题的最小程序,因为它必须是由其他东西产生的。
你应该注意一件事。 你正在使用的不是构造函数,它是一个对象初始化。 主要区别在于,当您使用对象初始值设定项时,生成的代码首先调用对象上的默认构造函数,然后设置属性/字段。
所以这段代码:
var myItem = new BaseItem
{
Name = "something",
Type = ItemType.Misc
}
实际上相当于这个:
var myItem = new BaseItem();
myItem.Name = "something";
myItem.Type = ItemType.Misc;
你可能想要的是定义一个构造函数,如下所示:
class BaseItem
{
public BaseItem(string name, ItemType type)
{
this.Name = name;
this.Type = type;
}
// ...
}
然后像这样使用它:
var myItem = new BaseItem("something", ItemType.Misc);
我猜想使用这种更明确的方法可能会间接解决你的bug,并且至少可能会使你的代码更不容易出错。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.