Страницы

Поиск по вопросам

воскресенье, 2 февраля 2020 г.

Конструкция return this

#c_sharp #net


Всем привет. Возник вопрос, что означает return this;, который обычно встречается
в методах? В пользовательском конструкторе this используется когда, поля класса и аргументы
конструктора имеют одинаковое имя, как здесь:

public IntValue(int value)
{
   this.value = value;
}


А что означает return this;, не очень понятно? Я думаю эту запись ввели для сокращения
кода, и возможно обойтись как-то без return this;, если такое возможно покажите? 
Если я правильно понял, то код, который я привёл ниже в реализация интерфейса - IEnumerable
возвращает экземпляр класса UserCollection приведенный к базовому интерфейсному типу
и this в данном случае это и есть ссылка на экземпляр класса UserCollection? 

namespace InterIEnumerable
{
    // Класс UserCollection коллекция (набор) объектов класса Element.
    // Для применения foreach, необходимо, чтобы класс реализовывал интерфейс - IEnumerable.
    public class UserCollection : IEnumerable, IEnumerator
    {
        public Element[] elementsArray = null;

        public UserCollection()
        {
            elementsArray = new Element[4];
            elementsArray[0] = new Element("A", 1, 10);
            elementsArray[1] = new Element("B", 2, 20);
            elementsArray[2] = new Element("C", 3, 30);
            elementsArray[3] = new Element("D", 4, 40);
        }

        // Указатель текущей позиции элемента в массиве.
        int position = -1;

        // ------------------------------------------------------------------------------------------------------------------
        // Реализация интерфейса IEnumerator.

        // Передвинуть внутренний указатель (position) на одну позицию.
        public bool MoveNext()
        {
            if (position < elementsArray.Length - 1)
            {
                position++;
                return true;
            }
            else
            {
                return false;
            }
        }

        // Установить указатель (position) перед началом набора.
        public void Reset()
        {
            position = -1;
        }

        // Получить текущий элемент набора. 
        public object Current
        {
            get { return elementsArray[position]; }
        }

        // -----------------------------------------------------------------------------------------------------------------
        // Реализация интерфейса - IEnumerable.

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this as IEnumerator;
        }
    }
}

    


Ответы

Ответ 1



Ээхм. this.value — это не магическая конструкция, означающая «не тот value, а другой, который я имею в виду». this — это ссылка на вполне конкретный объект, и this.value — это совершенно обыкновенное обращение к полю этого объекта. Этот вызов ничем не отличается от вызова obj.value по другой ссылке (если, конечно, тип ссылки obj такой же). Внутри нестатических методов объекта this является ссылкой на этот объект. Вне нестатических методов пользоваться this нельзя. Соответственно, если вы возвращаете ссылку на this, вы возвращаете ссылку на объект, в тором выполняется тот самый метод, откуда вы пытаетесь вернуть значение. Никакой мистики.

Ответ 2



Просто чтобы можно было делать не так: var x = new Smth(); x.DoSmth1(); x.DoSmth2(); x.DoSmth3(); x.DoSmth4(); var res = x.Value; а вот так (точнее, чтобы сделать эти записи эквивалентными): var x = new Smth(); var res = x.DoSmth1().DoSmth2().DoSmth3().DoSmth4().Value; потому что это может быть удобнее и позволять исключить лишнюю переменную. Это называется чейнингом (chaining) от слова "chain" - "цепь". кста, а в таких конструкциях есть оверхеад на возвращение обьекта или большее использование стека? Cтек используется так же, как раньше - ничего не меняется, поскольку вызовы последовательные, а не вложенные. Ну, потенциально может быть разница в 8 байт по сравнению с void, но я почти уверен, что возврат будет идти через регистр, а не через стек; да и 8 байт ни на что не влияют, поскольку они не зависят от числа вызовов. Сама по себе операция возврата тоже довольно дешёвая, плюс, она может хорошо сочетаться со следующим вызовом в цепочке (mov переместится из кода вызова в код функции) и получится один лишний возврат на всю цепочку. В общем, я считаю, что никакого оверхэда нет. А если и есть, то ни на что не повлияет - любая операция в коде будет больше, чем этот оверхэд. https://ideone.com/989mWC - все результаты в пределах погрешности html, body, #cs, pre { height: 100%; margin: 0; } pre, #cs { display: block; overflow: auto; font-family: monospace; white-space: pre; } pre { width: 14ch; float: left; border-right: 1px solid; margin-right: 8px; }
Успешно	#stdin #stdout 0.03s 15972KB
360000 3350
360000 2595
360000 422
360000 287

Успешно	#stdin #stdout 0.01s 131648KB
360000 2241
360000 2387
360000 234
360000 308

Успешно	#stdin #stdout 0.01s 131776KB
360000 2184
360000 1382
360000 181
360000 238

Успешно	#stdin #stdout 0.01s 131712KB
360000 1731
360000 1381
360000 179
360000 237


Ответ 3



это ссылка на экхемпляр класса public Object getThis() { return this; } Object me = new Object(); Object result = me.getThis() ;теперь result == me

Ответ 4



К другим ответам добавлю что public class MyClass { int value; public SetValue(int value) { this.value /*(1)*/ = value /*(2)*/; } } (1) это value самого объекта. (2) это value из аргумента функции Это удобно, что бы не плодить новых названий аргументов. И реально было задавать например value не через int newValue, что рождает путаницу а с аргументом с аналогичным именем.

Комментариев нет:

Отправить комментарий