Подтвердить что ты не робот

С# Структуры "this =...."

Я только что просматривал файл в отражателе и видел это в конструкторе структуры:

this = new Binder.SyntaxNodeOrToken();

Я еще не видел эту терминологию. Может кто-то объяснить, что это означает это назначение в С#. Это сложно для Google.

4b9b3361

Ответ 1

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

Пример:

using System;

class Test
{
    static void Main()
    {
        Point point = new Point(10, 20);
        point.ReplaceWith(new Point(2, 3));
        Console.WriteLine(point); // (2, 3)
    }
}

struct Point
{
    private readonly int x;
    private readonly int y;

    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public void ReplaceWith(Point other)
    {
        this = other;
    }

    public override string ToString()
    {
        return string.Format("({0}, {1})", x, y);
    }
}

Для получения дополнительной информации прочтите раздел 7.6.7 спецификации С# 4, который включает в себя:

  • [текст о его использовании в конструкторе структуры]

  • Когда this используется в первичном выражении внутри метода экземпляра или экземпляра экземпляра структуры, он классифицируется как переменная. Тип переменной - тип экземпляра структуры, в которой происходит использование.

    • Если метод или аксессор не является итератором, переменная this представляет структуру, для которой был вызван метод или аксессуар, и ведет себя точно так же, как параметр ref типа структуры.

    • [текст об итераторах]

Ответ 2

Если s1 и s2 являются структурами типа Foo, с полями f1, f2 и f3, типов t1, t2 и t3, утверждение s1 = s2 является семантически эквивалентным

  s1.f1 = s2.f1;
  s1.f2 = s2.f2;
  s1.f3 = s2.f3;

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

Оператор this = new Foo(whatever); находится в С# (*), эквивалентном

  Foo temp;
  call Foo constructor (out temp, whatever);
  this.f1 = temp.f1;
  this.f2 = temp.f2;
  this.f3 = temp.f3;

(*) Семантика конструктора Struct в vb.net отличается

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

Одна из причин, по которой я полагаю (вопреки мнению некоторых других людей), что структуры должны часто выставлять изменчивые поля, - это синтаксис вроде:

  // Assume myKVP is a field of type KeyValuePair<Wizzle, int>
  rr = new KeyValuePair<myKVP.Key, myKVP.Value+1>;

заставляет его выглядеть так, как будто myKVP будет ссылаться на другой экземпляр после назначения из того, что он удерживал раньше, когда на самом деле происходит следующее:

// Assumes backing fields are named _Key and _Value
// Note that C# won't allow one to write private fields directly, but the
// act of copying one struct instance to another copies all the fields,
// public and private, from the source instance to the destination.
  KeyValuePair<Wizzle, int> temp;
  temp._Key = myKVP.Key; // Constructor has access to backing fields
  temp._Value = myKVP.Value+1;
  myKVP._Key = temp._Key; // Struct assignment copies all fields, public and private
  myKVP.Value = temp.Value;

Другими словами, оператор не делает отчет myKVP другому экземпляру; вместо этого он создает новый экземпляр, мутирует старый экземпляр, перезаписывая его поля с именами нового экземпляра, а затем отбрасывает новый экземпляр. Если какой-то код оценивал myKVP.ToString(), в то время как указанное присвоение имело место, мутация повлияла бы на экземпляр myMVP, который был напечатан.

Структуры могут иметь полезную семантику, но так называемые "неизменные" структуры не являются. Нетривиальные структуры (те, для которых возможно создать значение, отличное от значения по умолчанию) являются изменяемыми тогда и только тогда, когда они хранятся в изменяемых местах хранения, независимо от какой-либо семантики, навязываемой типом. Самонастраивающиеся структуры, т.е. Структуры, которые мутируют this в любых методах, кроме конструкторов и свойств, могут иметь некоторые неожиданные действия, поскольку компиляторы не могут запретить вызов других методов, которые будут мутировать this в неизменяемой структуре экземпляры. Однако публичное раскрытие структурных полей не представляет такой опасности. Поскольку все поля изменяемого экземпляра нетривиальной структуры по своей сути изменяемы, независимо от любых попыток, которые структура может создать для мутации, и все поля неизменяемого экземпляра структуры являются неизменяемыми, даже если они открыты, структура который стремится сделать свои поля "неизменными", действительно говорит ложь. Ложь, которая может время от времени быть полезной (например, если содержимое поля должно подчиняться определенным инвариантам), но которое не должно быть сказано без какой-либо реальной причины.