簡體   English   中英

C#枚舉的奇怪行為

[英]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類的代碼或引入Ins1Ins2變量的代碼,那么在對其進行更改時重新編譯所有程序集至關重要。 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.

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