Свойства C #, зачем проверять равенство перед присваиванием - PullRequest
12 голосов
/ 16 августа 2011

Почему я вижу, как люди реализуют такие свойства?
Какой смысл проверять, равно ли значение текущему значению?

public double? Price
{
    get
    {
        return _price;
    }
    set
    {
        if (_price == value)
            return;
        _price = value;
    }
}

Ответы [ 4 ]

28 голосов
/ 16 августа 2011

В этом случае это будет спорный вопрос;однако, в случае, когда есть связанный побочный эффект (обычно событие), это избегает тривиальных событий.Например:

set
{
    if (_price == value)
        return;
    _price = value;
    OnPriceChanged(); // invokes the Price event
}

Теперь, если мы сделаем:

foo.Price = 16;
foo.Price = 16;
foo.Price = 16;
foo.Price = 16;

, мы не получим 4 события;мы получаем самое большее 1 (может быть 0, если это уже 16).

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

set
{
    if (_price == value)
        return;
    if(value < 0 || value > MaxPrice) throw new ArgumentOutOfRangeException();
    OnPriceChanging();
    _price = value;
    OnPriceChanged();
}
6 голосов
/ 16 августа 2011

Это не ответ, более того: это основанный на доказательствах ответ на претензию (в другом ответе), которую быстрее проверить, чем назначить. Короче говоря: нет, это не так. Без разницы вообще . Я получаю (за ненулевое значение int):

AutoProp: 356ms
Field: 356ms
BasicProp: 357ms
CheckedProp: 356ms

(с некоторыми небольшими вариациями последовательных прогонов - но, по сути, все они занимают одно и то же время в любом разумном округлении - при выполнении чего-то 500 МИЛЛИОНОВ раз мы можем игнорировать разницу в 1 мс)

На самом деле, если мы изменим на int?, я получу:

AutoProp: 714ms
Field: 536ms
BasicProp: 714ms
CheckedProp: 2323ms

или double? (как в вопросе):

AutoProp: 535ms
Field: 535ms
BasicProp: 539ms
CheckedProp: 3035ms

так что не помощник по производительности!

с тестами

class Test
{
    static void Main()
    {
        var obj = new Test();
        Stopwatch watch;
        const int LOOP = 500000000;
        watch = Stopwatch.StartNew();
        for (int i = 0; i < LOOP; i++)
        {
            obj.AutoProp = 17;
        }
        watch.Stop();
        Console.WriteLine("AutoProp: {0}ms", watch.ElapsedMilliseconds);

        watch = Stopwatch.StartNew();
        for (int i = 0; i < LOOP; i++)
        {
            obj.Field = 17;
        }
        watch.Stop();
        Console.WriteLine("Field: {0}ms", watch.ElapsedMilliseconds);

        watch = Stopwatch.StartNew();
        for (int i = 0; i < LOOP; i++)
        {
            obj.BasicProp = 17;
        }
        watch.Stop();
        Console.WriteLine("BasicProp: {0}ms", watch.ElapsedMilliseconds);

        watch = Stopwatch.StartNew();
        for (int i = 0; i < LOOP; i++)
        {
            obj.CheckedProp = 17;
        }
        watch.Stop();
        Console.WriteLine("CheckedProp: {0}ms", watch.ElapsedMilliseconds);

        Console.ReadLine();
    }
    public int AutoProp { get; set; }
    public int Field;

    private int basicProp;
    public int BasicProp
    {
        get { return basicProp; }
        set { basicProp = value; }
    }

    private int checkedProp;
    public int CheckedProp
    {
        get { return checkedProp; }
        set { if (value != checkedProp) checkedProp = value; }
    }
}
1 голос
/ 21 ноября 2013

Предположим, мы не обрабатываем события, связанные с изменениями. Я не думаю, что сравнение быстрее, чем оценка. Это зависит от типа данных. Допустим, у вас есть строка. Сравнение намного длиннее в худшем случае, чем простое присваивание, в котором член просто меняет ссылку на ссылку новой строки. Так что я думаю, что лучше в этом случае назначить сразу. В случае простых типов данных это не оказывает реального влияния.

0 голосов
/ 16 августа 2011

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

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