Unity 实用技巧 之 C#编程优化——枚举

Unity C#编程优化——枚举

我讨厌C#的枚举类型。我都会尽量避免它。考虑下面关于行星枚举的这个例子:

[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
public enum Planet {
     MERCURY,
     VENUS,
     EARTH,
     MARS,
     JUPITER,
     SATURN,
     URANUS,
     NEPTUNE,
     PLUTO // Pluto is a planet!!!
}


起初,这样的定义还算好,直到需要产生一个行星的质量。所以我们做这样的事情:

[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
// 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枚举用类表示的一个版本:


   
[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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;
            }
        }
    }


为了保持不变性,所有成员变量应该是只读的。 一旦他们被分配,他们将不能再被改变。 这很重要,因为作为枚举,它的内部值不应该改变。 然后将每个枚举值实现为该类的静态只读实例。

这是怎么用的? 与正常枚举是一样的,如下使用:


[C#]  纯文本查看  复制代码
?
 
1
2
3
4
5
// 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实例? 这很容易 通常我为这些转换添加了一个公共和静态方法。 例如:


[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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:
[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
private static Dictionary< string , Planet> 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];
}


您可以支持您喜欢的任何类型的转换。
还有更多的你可以做。 您现在可以添加功能。 你可以这样做:

[C#]  纯文本查看  复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
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();
});


通过简单地将你的枚举变成一个类,你已经将它升级到更有组织的东西,而且更加功能强大。 您也可以使用反射和继承等先进功能,但大多数情况下,您不需要。
希望这可以帮助你。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值