寻找更好的方法来处理大量参数

时间:2012-05-12 15:04:27

标签: c#

我已经为游戏实现了一种转向行为,并且每次使用编辑器,设计师应该能够(当前)选择七个参数,无论它们是0,随机还是设定数量,以及在后两者的情况下,随机范围应该下降或变量应该得到的设定量。设置将保存在文件中,并且必须能够随时加载。

我最终得到的是查看构造函数和整个,很多字段和属性的痛苦。 我正在寻找一种更智能的方法来解决这个问题,尤其是在以后添加更多参数时。

public enum SteerType
{
    None,
    Random,
    Variable
}

public IdleSteering(SteerType rotationOnIntervalType, int rotationOnInterval, 
                    SteerType rotationOnCollisionType, int rotationOnCollision,
                    SteerType breakIntervalType, int breakInterval,  
                    SteerType breakTimeType, int breakTime, 
                    SteerType rotationOnBreakType, int rotationOnBreak, 
                    SteerType rangeFromSpawnType, int rangeFromSpawn, 
                    SteerType speedType, int speed)
    {
        _rotationOnIntervalType = rotationOnIntervalType;
        _rotationOnInterval = rotationOnInterval;

        _rotationOnCollisionType = rotationOnCollisionType;
        _rotationOnCollision = rotationOnCollision;

        <...> //And this five more times
    }

每个参数的下一个块,所以也是七次。

private SteerType _rotationOnIntervalType;
    private float _randomRotationOnInterval;
    private float _rotationOnInterval;
    public float RotationOnInterval
    {
        get
        {
            switch (_rotationOnIntervalType)
            {
                case SteerType.None:
                    return 0;
                case SteerType.Random:
                    if (_randomRotationOnInterval.Equals(0))
                        _randomRotationOnInterval =
                            MathHelper.ToRadians((float)(-Static.Random.NextDouble() + Static.Random.NextDouble()) * _rotationOnInterval);
                    return _randomRotationOnInterval;
                case SteerType.Variable:
                    return _rotationOnInterval;
            }
            return 0;
        }
    }

5 个答案:

答案 0 :(得分:3)

使用设置对象 - 将这些参数重构为一个类并将该类传递进去。您可以添加其他参数而不会出现问题。

这称为parmeter object refactoring,已在BCL的多个地方使用 - ProcessStartInfo类为一。

这种方法的另一个好处是,您可以使用它们分别对类别进行序列化和反序列化。

答案 1 :(得分:3)

建议创建一个类来保存2个/配对值,然后将其分组到一个集合中:

public class Steering
{
    public SteerType SteerType{get;set}
    public int Amount{get;set}
}

List<Steering> userSteering = new List<Steering>
  {
     //initialize your list
  };

//pass that list into a constructor.

在您的IdleSteering课程中结束:

private List<Steering> steeringValues;

public IdleSteering(List<Steering> userSteering)
{
    steeringValues = userSteering;
}

//we can now use LINQ to find any particular steering value.
int braking = steeringValues.SingleOrDefault(x=>x.SteerType==Random).Amount;

在所有方法之间传递和使用该集合。

答案 2 :(得分:2)

最明显的解决方案是在参数中查找模式。我看到的是,您有SteerType的组合以及代表速度的int。然后,您可以多次使用此组合,每个组合一次用于几种不同的状态。

鉴于此,您可以将这两件事合并为一个类:

public class SteerSettings
{
    public SteerType Type { get; private set; }
    public int Interval { get; private set; }

    public SteerSettings(SteerType type, int interval)
    {
        Type = type;
        Interval = interval;
    }
}

然后将构造函数更改为:

public IdleSteering(SteerSettings rotationOn, SteerSettings collision, 
                    SteerSettings break,  SteerSettings breakTime, 
                    SteerSettings rotationOnBreak, SteerSettings rangeFromSpawn, 
                    SteerSettings speed)
    {
        ...
    }

更积极的方法是采用它并创建一个代表各种状态的新枚举,并在Dictionary中使用它来指定每个州的各种设置。

public enum SteerState
{
    RotationOn,
    Collision,
    Break,
    BreakTime,
    RotationOnBreak,
    RangeFromSpawn,
    Speed
}

public IdleSteering(IDictionary<SteerState, SteerSettings> settings)
{
    ...
}

答案 3 :(得分:0)

看起来你有一个可能无限长的集合,由不同的参数组成。

为什么不用字典来制作它,如下:

public IdleSteering(IDictionary<SteerType,int> steerSettings)

然后通过字典键设置并获取值。

?!

答案 4 :(得分:0)

我将使用SteerType和RotationValue进行另一次旋转(以及你的getter,虚拟,如果需要),并且将在构造函数中默认参数(.NET 4.0 req'ed):

public IdleSteering(Rotation interval=null, Rotation collission=null)
    {

        _rotationOnIntervalType = rotationOnIntervalType??new Rotation(...);
        _rotationOnInterval = rotationOnInterval??new Rotation(...);
        ...
    }

然后你会打电话:

var idleSteering = new IdleSteering();

当然,如果属性可以默认......