производительность параметра c # - PullRequest
2 голосов
/ 16 ноября 2010

Итак, я должен вызывать метод довольно регулярно как часть шаблона. Это выглядит примерно так:

DoWork(new TimeSpan(0, 0, 2, 0));

или в другой части кода:

DoWork(new TimeSpan(0, 0, 6, 50));

В каждом случае параметр никогда не меняется, и я недавно проснулся и понял, что такое повышение производительности, чтобы продолжать создавать параметр для каждого вызова. У меня есть решение:

// instance field
TimeSpan _cachedValue = new TimeSpan(0, 0, 2, 0);
// and when called, 
DoWork(this._cachedValue)

Это все довольно очевидно, но проблема, с которой я столкнулся, заключается в хранении значения параметра в поле ... его беспорядок в уже раздутом классе (например, в одном классе я бы вызвал метод do work с 10 или около того вариантов много тысяч раз каждый - так вот десять дополнительных полей).

Было бы здорово, однако, если бы я мог сделать что-то вроде этого:

DoWork([DoesNotChange()]new TimeSpan(0, 0, 2, 0));

Этот теоретический атрибут параметра указывает на то, что для данного конкретного вызова значение нужно только один раз обработать, а затем повторно передать методу.

Так что-нибудь подобное возможно? Или я только что сошел с ума?

Приветствия

EDIT:

Ничего себе, ребята, работайте быстро, спасибо. Что касается моего вопроса, я должен был научиться в прошлый раз не слишком упрощать - извините. Я собираюсь опубликовать фактический фрагмент кода для ясности. Этот класс используется для привязки данных в приложении Silverlight. Я использую строгую типизацию для событий PropertyChanged для удобства сопровождения:

internal class BasicDataClass : INotifyPropertyChanged
{
    private readonly Expression<Func<double>> _propertySelector;
    private double _someFieldA;
    private double _someFieldB;
    private double _someFieldC;

    public BasicDataClass()
    {
        _propertySelector = () => SomeFieldC;
    }

    /// <summary>
    /// This is fastest
    /// </summary>
    public double SomeFieldA
    {
        get { return _someFieldA; }
        set
        {
            if (!_someFieldA.Equals(value))
            {
                _someFieldA = value;
                PropertyChanged.Raise(this, "SomeFieldA");
            }
        }
    }

    /// <summary>
    /// This is many times slower
    /// </summary>
    public double SomeFieldB
    {
        get { return _someFieldB; }
        set
        {
            if (!_someFieldB.Equals(value))
            {
                _someFieldB = value;
                PropertyChanged.Raise(() => SomeFieldB);
            }
        }
    }

    /// <summary>
    /// This is only, very slightly slower than A
    /// but requires an extra field
    /// </summary>
    public double SomeFieldC
    {
        get { return _someFieldC; }
        set
        {
            if (!_someFieldC.Equals(value))
            {
                _someFieldC = value;
                PropertyChanged.Raise(_propertySelector);
            }
        }
    }

    #region INotifyPropertyChanged Members

    /// <summary>
    /// The property changed.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

И для справки: методы расширения Raise:

    public static void Raise<TValue>(
        this PropertyChangedEventHandler handler, Expression<Func<TValue>> propertySelector)
    {
        if (handler != null)
        {
            var memberExpression = propertySelector.Body as MemberExpression;
            if (memberExpression != null)
            {
                object sender = ((ConstantExpression)memberExpression.Expression).Value;
                handler(sender, new PropertyChangedEventArgs(memberExpression.Member.Name));
            }
        }
    }

    public static void Raise(this PropertyChangedEventHandler handler, object sender, string propertyName)
    {
        if (handler != null)
        {
                handler(sender, new PropertyChangedEventArgs(propertyName));
        }
    }

Опять же, извините, что не уточнил.

Ответы [ 4 ]

6 голосов
/ 16 ноября 2010

Это в основном константы, верно?Так почему бы не заполнить статические поля ими:

private static readonly TimeSpan RpcTimeOut = TimeSpan.FromSeconds(2);

...
DoWork(RpcTimeOut);

Я думаю, что это чище, чем пытаться приписать параметр.

Имея эти поля как static , вы нена самом деле не будет вздутие живота любых объектов - для каждого домена приложений будет только одно значение.

0 голосов
/ 16 ноября 2010

Практически. Если вы собираетесь делать поле экземпляра, вы можете также сделать переменные статическими членами только для чтения:

static readonly TimeSpan t = new TimeSpan(0, 0, 2, 0);

Делая это так вместоПри построении встроенных TimeSpans у вас также есть возможность дать переменным описательное имя.

Теоретически. Я не думаю, что ваше предложение использовать какой-либо встроенный атрибут или директиву будет работать впрактика, хотя CLR теоретически это поддерживает.Вам нужно будет убедить компилятор применить «постоянное сворачивание» к вашему new TimeSpan(), и я не знаю, как заставить это сделать.уменьшить выражение, состоящее из констант в одну константу.Таким образом, выражение не нужно оценивать во время выполнения.Теоретически struct может быть константой, а конструктор TimeSpan является детерминированным, поэтому константное сворачивание возможно.но даже TimeSpan.MaxValue не инициализируется таким образом [1].

[1] Я проверил это с помощью инструмента Reflector.

0 голосов
/ 16 ноября 2010

Если вы хотите, чтобы переменная "сработала" (я предполагаю, что вы имеете в виду присвоение значения?), Используйте постоянную TimeSpan.

0 голосов
/ 16 ноября 2010

Вы можете извлечь их в файл конфигурации - таким образом вы можете изменить их, если вам нужно, и вызовы для чтения конфигурации (используя System.Configuration) будут кэшированы после первого чтения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...