繁体   English   中英

如何重构泛型if语句以进行类型检查

[英]How to refactor the pervasive if statement for type check

我正在使用已经使用了大约十年的旧系统,在其中定义了一种基本数据结构,如下所示:

[Serializable()]
public class DataClass
{
    private Array _values;
    private readonly Type _valueType;

    public DataClass(Array tmpArray, Type tmpType)
    {
        _values = tmpArray;
        _valueType = tmpType;
    }

    public Array GetValues()
    {
        return _values;
    }

    public Type ValueType
    {
        get { return _valueType; }
    }

    public void SetValues(Array newValues, int fromIndex)
    {
        // 1. type check, if _values and newValues don't share same data type, throws an exception

        // 2. length check
        if (fromIndex + newValues >= _values.Length)
           throws new InvalidDataException();

        // 3. set values
        for (var i = fromIndex; i < newValues.Length; i++)
             _values.SetValue(newValues.GetValue(i - fromIndex), i);  
    }

    ...blahblah
}

我相信他们的倡议是他们希望仅使用一个类来支持不同的数据类型,例如

new DataClass(new int[]{1,2,3,4}, typeof(int));

new DataClass(new float[]{1f,2f,3f,4f}, typeof(float));

现在我想给init DataClass使用默认值,分析后,我发现,API SetValues进行更长时间的阵列(很慢boxingunboxing我相信),并使得程序不太敏感,我决定使用通用和大量的if else语句为了加快速度,例如:

void InitValues(DataClass data)
{
    if (data.ValueType == typeof(int))
        InitWith(data, -1);
    else
    if (data.ValueType == typeof(double))
        InitWith(data, -9.99d);

    ...blahblah

}

void InitWith<T>(DataClass data, T defaultValue)
{
    // much faster
    var array = (T[])data.GetValues();
    for (var i = 0; i < array.Length; i++)
         array[i] = defaultValue;
}     

但是我有很多像InitValues这样的性能关键型方法。由于DataClass支持的值类型DataClass ,因此编写和维护这样的代码很DataClass

鉴于这一事实,我没有自己的源代码, DataClass ,我不能做任何改变DataClass 我想知道是否有一种重构的方法,以便可以在一个地方处理所有类型为if语句?

鉴于您不允许更改DataClass ,我们需要使DataClass高效。 一种方法是使用字典将类型映射到操作/方法。 我们只需要初始化一次这些字典。 这是此类的示例。

class ConsumerClass // the one which uses DataClass objects
{
    // All the Mappings required by this consumer class
    readonly Dictionary<Type, Action<DataClass>> InitMap = new Dictionary<Type, Action<DataClass>>();
    readonly Dictionary<Type, Action<DataClass>> DoSomethingAMap = new Dictionary<Type, Action<DataClass>>();
    readonly Dictionary<Type, Action<DataClass>> DoSomethingBMap = new Dictionary<Type, Action<DataClass>>();

    // Constructor
    public ConsumerClass()
    {
        // Initialize all the mappings for all the required types for this consumer class here. 
        // This is a one time overhead, but will definitely speedup the methods within this class
        // You could move this part further up the hierarchy of inheritance, to avoid repetitions in every other consumer class.

        // For int
        InitMap.Add(typeof(int), data => InitWith(data, -1));
        DoSomethingAMap.Add(typeof(int), DoSomethingA<int>);
        DoSomethingBMap.Add(typeof(int), DoSomethingB<int>);

        // For double
        InitMap.Add(typeof(double), data => InitWith(data, -9.99d));
        DoSomethingAMap.Add(typeof(double), DoSomethingA<double>);
        DoSomethingBMap.Add(typeof(double), DoSomethingB<double>);

        // other types, if needed by this consumer
    }

    void InitValues(DataClass data)
    {
        // This takes care of your if s
        InitMap[data.ValueType].Invoke(data);
    }
    void InitWith<T>(DataClass data, T defaultValue)
    {
        // much faster
        var array = (T[])data.GetValues();
        for (var i = 0; i < array.Length; i++)
            array[i] = defaultValue;
    }

    void DoSomethingA(DataClass data)
    {
        DoSomethingAMap[data.ValueType].Invoke(data);
    }
    void DoSomethingA<T>(DataClass data)
    {
        var array = (T[])data.GetValues();
        // do something
    }

    void DoSomethingB(DataClass data)
    {
        DoSomethingBMap[data.ValueType].Invoke(data);
    }
    void DoSomethingB<T>(DataClass data)
    {
        var array = (T[])data.GetValues();
        // do something
    }
}

构造函数中有一些冗余代码,因此仍然有更好的方法来编写此机制。 但是,您应该了解如何清理ifs并仍然提高性能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM