Поведение чрезвычайно похоже на Array.Resizeметод в .NET. Чтобы понять, что происходит, может быть полезно взглянуть на историю .токена в C, C ++, Java, C # и Swift.
В C структура - это не более чем совокупность переменных. Применение .к переменной типа структуры приведет к доступу к переменной, хранящейся в структуре. Указатели на объекты не содержат совокупности переменных, но идентифицируют их. Если имеется указатель, который идентифицирует структуру, ->оператор может использоваться для доступа к переменной, хранящейся в структуре, идентифицированной указателем.
В C ++ структуры и классы не только агрегируют переменные, но и могут присоединять к ним код. Использование .для вызова метода приведет к тому, что метод будет воздействовать на содержимое самой переменной ; использование ->переменной, которая идентифицирует объект, попросит этот метод воздействовать на объект, идентифицируемый переменной.
В Java все пользовательские типы переменных просто идентифицируют объекты, и вызов метода для переменной сообщит методу, какой объект идентифицирован переменной. Переменные не могут содержать какой-либо тип составного типа данных напрямую, и нет никаких средств, с помощью которых метод может получить доступ к переменной, для которой он вызывается. Эти ограничения, хотя и семантически ограничивающие, значительно упрощают время выполнения и облегчают проверку байт-кода; такие упрощения позволили снизить затраты ресурсов Java в то время, когда рынок был чувствителен к таким проблемам, и, таким образом, помогли ему завоевать популярность на рынке. Они также подразумевали, что не было необходимости в токене, эквивалентном .используемому в C или C ++. Хотя Java могла бы использоваться так ->же, как C и C ++, создатели решили использовать односимвольный. так как это не было нужно для каких-либо других целей.
В C # и других языках .NET переменные могут либо идентифицировать объекты, либо напрямую содержать составные типы данных. При использовании для переменной составного типа данных .действует на содержимое переменной; при использовании на переменную ссылочного типа, .действует на объект идентифицированнойпо этому. Для некоторых видов операций семантическое различие не особенно важно, но для других это так. Наиболее проблематичными являются ситуации, в которых метод составного типа данных, который изменяет переменную, для которой он вызывается, вызывается для переменной только для чтения. Если предпринята попытка вызвать метод для значения или переменной только для чтения, компиляторы обычно копируют переменную, позволяют методу воздействовать на нее и отбрасывают переменную. Обычно это безопасно для методов, которые только читают переменную, но не безопасно для методов, которые записывают в нее. К сожалению, у .does пока нет средств указать, какие методы можно безопасно использовать с такой заменой, а какие нет.
В Swift методы на агрегатах могут явно указывать, будут ли они изменять переменную, для которой они вызываются, а компилятор запрещает использование методов с переменными переменными только для чтения (вместо того, чтобы заставлять их изменять временные копии переменной, которые затем быть сброшенным). Из-за этого различия использование .токена для вызова методов, которые изменяют переменные, для которых они вызываются, намного безопаснее в Swift, чем в .NET. К сожалению, тот факт, что один и тот же .токен используется для этой цели, чтобы воздействовать на внешний объект, идентифицируемый переменной, означает возможность путаницы.
Если был машина времени и вернулся к созданию C # и / или Свифта, можно было бы задним числом избежать большой части путаницы вокруг таких вопросов, имея язык используют .и ->маркер в моде гораздо ближе к использованию C ++. Методы как агрегатов, так и ссылочных типов могут использоваться .для воздействия на переменную, для которой они были вызваны, и ->для воздействия на значение (для композитов) или на определенную вещь (для ссылочных типов). Однако ни один из этих языков не разработан таким образом.
В C # обычной практикой для метода для изменения переменной, для которой он вызывается, является передача переменной в качестве refпараметра методу. Таким образом, вызов « Array.Resize(ref someArray, 23);когда someArrayидентифицирует массив из 20 элементов» приведет someArrayк идентификации нового массива из 23 элементов, не влияя на исходный массив. Использование refпроясняет, что метод должен изменить переменную, для которой он вызывается. Во многих случаях полезно иметь возможность изменять переменные без использования статических методов; Быстрые адреса, что означает использование .синтаксиса. Недостатком является то, что он теряет ясность относительно того, какие методы воздействуют на переменные и какие методы воздействуют на значения.