Где ограничение на общий тип с двойным типом параметров - бокс / распаковка? - PullRequest
0 голосов
/ 29 февраля 2012

У меня есть класс, который определяется следующим образом. Интерфейс и конкретный тип имеют параметр типа, который, как я ожидаю, будет double, int, decimal или DateTime. Я добавил ограничение where в IComparable, однако этот класс выполняет некоторые тяжелые числовые операции, поэтому я хочу избежать упаковки и распаковки. Определения классов следующие:

public interface INumericClass<T1, T2>  where T1:IComparable 
    where T2:IComparable
{
    void DoLongNumericOperation();
}  

public class NumericClass<T1, T2> : INumericClass<T1, T2> where T1:IComparable 
    where T2:IComparable 
{     
    private IList _innerArray1 = new T1[1000000];
    private IList _innerArray2 = new T2[1000000];      
    public void DoLongNumericOperation()     
    {         
        for(int i = 0; i < _innerArray1.Count; i++)         
        {             
            // some computation goes on in here             
            // for example, it could be             
            double aConstant = 123.45;
            double aScalar = 56.7;
            _innerArray1[i] = (Convert.ToDouble(_innerArray1[i]) * aConstant + aScalar);
            _innerArray2[i] = (Convert.ToDouble(_innerArray2[i]) * aConstant + aScalar);         
        }     
    } 
} 

Эти классы будут объявлены и использованы при вызове кода примерно так:

var numeric = new NumericClass<int, double>();
numeric.DoLongNumericComputation(); 

Теперь внутренне способ, которым я работаю с несколькими типами, заключается в приведении T к удвоению. Однако я обеспокоен тем, что, поскольку я указал, что T является параметром типа IComparable, происходит распаковка / упаковка. Кроме того, DateTime предоставляет дополнительные накладные расходы. В этом случае я делаю преобразование свойства .Ticks в double и оперируем этим.

Я приветствую любую информацию о том, что происходит под капотом в CLR, а также предложения по улучшению производительности, такие как изменения API для строгого ввода каждой из числовых операций для улучшения производительности и использования памяти.

Редактировать: Я должен также добавить, что приведенная выше реализация является неоптимальной, так как если вы объявляете NumericClass, он начинает бросать бросок из Tx в удвоение. Я могу только предположить, что это происходит через IComparable, хотя я не уверен.

Ответы [ 2 ]

2 голосов
/ 29 февраля 2012

Не видя более полного примера, вот что я могу порекомендовать.

public interface IConvertToDouble<T>
   where T : IComparable
{
    double Convert(T input);
    T ConvertBack(double input);
}

public class NumericClass<T, U>
    where T : IComparable,
          U : IComparable
{
    private IConvertToDouble<T> _tConverter;
    private IConvertToDouble<U> _uConverter;
    private List<T> _internalTs;
    private List<U> _internalUs;

    public NumericClass(IConvertToDouble<T> tConverter, IConvertToDouble<U> uConverter)
    {
        _tConverter = tConverter;
        _uConverter = uConverter;
        _internalTs = new List<T>();
        _internalUs = new List<U>();
    }

    public void DoLongNumericOperation()
    {
        for(int i = 0; i < innerArray.Length; i++)
        {
            // some computation goes on in here
            // for example, it could be
            double aConstant = 123.45;  
            double aScalar = 56.7
            _internalTs[i] = _tConverter.ConvertBack(_tConverter.Convert(_internalTs[anIndex]) * aConstant + aScalar);
            _internalUs[i] = _uConverter.ConvertBack(_uConverter.Convert(_internalUs[anIndex]) * aConstant + aScalar);
        }
    }
}

Теперь вам не нужно приводить универсальные объекты или иметь логику, специфичную для типа, в NumericClass.

1 голос
/ 29 февраля 2012
...