Unity C#編程優化——枚舉

考慮下面關於行星枚舉的這個例子:
public enum Planet {
    MERCURY,
    VENUS,
    EARTH,
    MARS,
    JUPITER,
    SATURN,
    URANUS,
    NEPTUNE,
    PLUTO // Pluto is a planet!!!
}
起初,這樣的定義還算好,直到需要產生一個行星的質量。所以我們做這樣的事情:
// Returns the mass of the planet in 10^24 kg
public float GetMass(Planet planet) {
    switch(planet) {
        case Planet.MERCURY:
            return 0.330;
        case Planet.VENUS:
            return 4.87f;
        case Planet.EARTH:
            return 5.97f;
        ...
        case Planet.PLUTO:
            return 0.0146f;
    }
}

行星直徑又如何? 另一個switch語句? 密度怎麼樣? 重力? 逃跑速度? 只要想想你將要維護的switch語句的數量。 你可以爭辯說,你可以使用一個Dictionary,但仍然笨重。 每個數據的Dictionary都要映射?沒門。

有一個更好的方法,我會告訴你如何。 這可能已經是非Unity程序員的常識,但我想在我的博客中再次提出這個冗餘的主題,對於那些可能不知道這一點的人來說,特別是初學者。 我也想保持簡單。

基本上,你可以使用類作爲枚舉。 爲什麼用類? 這確實表現的更好 您可以存儲任意數量的任意數據。 您甚至可以存儲例程或功能。 你可以做很多事情。 唯一的要求是它是不可變的,這意味着類一個實例的狀態在整個程序期間都不能改變。以下是Planet枚舉用類表示的一個版本:
public class Planet {
       // The different values
       public static readonly Planet MERCURY = new Planet(0, 0.330f, 4879, 5427, 3.7f);
       public static readonly Planet VENUS = new Planet(1, 4.87f, 12104, 5243, 8.9f);
       public static readonly Planet EARTH = new Planet(2, 5.97f, 12756, 5514, 9.8f);
       public static readonly Planet MARS = new Planet(3, 0.642f, 6792, 3933, 3.7f);
       public static readonly Planet JUPITER = new Planet(4, 1898.0f, 142984, 1326, 23.1f);
       public static readonly Planet SATURN = new Planet(5, 568.0f, 120536, 687, 9.0f);
       public static readonly Planet URANUS = new Planet(6, 86.8f, 51118, 1271, 8.7f);
       public static readonly Planet NEPTUNE = new Planet(7, 102.0f, 49528, 1638, 11.0f);
       public static readonly Planet PLUTO = new Planet(8, 0.0146f, 2370, 2095, 0.7f);
       // Use readonly to maintain immutability
       private readonly int id;
       private readonly float mass; // in 10^24 kg
       private readonly int diameter; // in km
       private readonly int density; // in kg/m^3
       private readonly float gravity; // in m/s^2
       // We use a private constructor because this should not be instantiated
       // anywhere else.
       private Planet(int id, float mass, int diameter, int density, float gravity) {
           this.id = id;
           this.mass = mass;
           this.diameter = diameter;
           this.density = density;
           this.gravity = gravity;
       }
       public int Id {
           get {
               return id;
           }
       }
       public float Mass {
           get {
               return mass;
           }
       }
       public int Diameter {
           get {
               return diameter;
           }
       }
       public int Density {
           get {
               return density;
           }
       }
       public float Gravity {
           get {
               return gravity;
           }
       }
   }
爲了保持不變性,所有成員變量應該是隻讀的。 一旦他們被分配,他們將不能再被改變。 這很重要,因爲作爲枚舉,它的內部值不應該改變。 然後將每個枚舉值實現爲該類的靜態只讀實例。

這是怎麼用的? 與正常枚舉是一樣的,如下使用:
// Use it like an enum
ship.TargetPlanet = Planet.NEPTUNE;
// Want to know the target planet's mass?
float mass = ship.TargetPlanet.Mass;
// Density?
int density = ship.TargetPlanet.Density;
我們已經消除了切換語句或字典來維護不同行星信息的需要。 想要一個新的行星狀態? 只需添加一個新的成員變量並在實例化上指定它們。
如何從其他數據類型轉換? 喜歡說從int id轉換爲Planet實例? 這很容易 通常我爲這些轉換添加了一個公共和靜態方法。 例如:
public class Planet {
    // The different values
    public static readonly Planet MERCURY = new Planet(0, 0.330f, 4879, 5427, 3.7f);
    public static readonly Planet VENUS = new Planet(1, 4.87f, 12104, 5243, 8.9f);
    public static readonly Planet EARTH = new Planet(2, 5.97f, 12756, 5514, 9.8f);
    public static readonly Planet MARS = new Planet(3, 0.642f, 6792, 3933, 3.7f);
    public static readonly Planet JUPITER = new Planet(4, 1898.0f, 142984, 1326, 23.1f);
    public static readonly Planet SATURN = new Planet(5, 568.0f, 120536, 687, 9.0f);
    public static readonly Planet URANUS = new Planet(6, 86.8f, 51118, 1271, 8.7f);
    public static readonly Planet NEPTUNE = new Planet(7, 102.0f, 49528, 1638, 11.0f);
    public static readonly Planet PLUTO = new Planet(8, 0.0146f, 2370, 2095, 0.7f);
    // This can be used to loop through all planets
    public static Planet[] ALL = new Planet[] {
        MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE, PLUTO
    };
    // Converts the specified id to a Planet instance
    public static Planet Convert(int id) {
        for(int i = 0; i < ALL.Length; ++i) {
            if(ALL.Id == id) {
                return ALL;
            }
        }
        // return ALL[id] could also work here but what if a non sequential id is used?
        throw new Exception("Cannot convert {0} to a Planet.".FormatWith(id));
    }
    ...
}
// Usage
Planet planet = Planet.Convert(someIntPlanet);


想從字符串ID轉換? 添加將保存此值的字符串成員變量。 而不是使用諸如ALL []的數組,您可以使用如下所示的Dictionary:
private static Dictionary<string, planet="" style="color: rgb(34, 34, 34); font-family: 微軟雅黑; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;"> ALL = new Dictionary<string, planet="">() {
    { MERCURY.TextId, MERCURY },
    { VENUS.TextId, VENUS },
    { EARTH.TextId, EARTH },
    ...
    { PLUTO.TextId, PLUTO },
};
// Converts the specified string to a Planet instance
public static Planet Convert(string id) {
    return ALL[id];
}


您可以支持您喜歡的任何類型的轉換。
還有更多的你可以做。 您現在可以添加功能。 你可以這樣做:
Planet currentPlanet = Planet.VENUS;
currentPlanet.ApplyGravity(ship);
The coolest thing for me is you can specify different actions or behavior to the enum values. Something like this (It’s very contrived but you get the idea.):
public static readonly Planet EARTH = new Planet(2, 5.97f, 12756, 5514, 9.8f, delegate(Ship ship) {
    // Actions on land of ship
    ship.AddFood(1000);
    ship.RetireCrew();
    ship.RecruitNewCrew();
});
public static readonly Planet MARS = new Planet(3, 0.642f, 6792, 3933, 3.7f, delegate(Ship ship) {
    // Actions on land of ship
    ship.DeductFood(50);
    ship.Research();
    ship.Mine();
});


通過簡單地將你的枚舉變成一個類,你已經將它升級到更有組織的東西,而且更加功能強大。 您也可以使用反射和繼承等先進功能,但大多數情況下,您不需要。

 更多unity2018的功能介紹請到paws3d學習中心查找。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章