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

Переопределение автоматического свойства

так как это

public int MyInt{ get; set;}

эквивалентно

private int _myInt;
public int MyInt{ get{return _myInt;} set{_myInt = value;} }

при создании автоматического свойства virtual

public virtual int MyInt{ get; set;}

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

public override int MyInt{ get{return someVar;} set{someVar = value;} }

У этого дочернего класса теперь есть неудобное и скрытое выделение _myInt?

4b9b3361

Ответ 1

Короткий ответ. Да, Child выделяет все поля класса Base, поэтому он все еще имеет выделенное поле поддержки. Однако вы не можете получить к нему доступ иначе, чем через свойство Base.MyInt.

Длинный ответ:

Результаты быстрой разборки.

Base и Child реализация классов:

public class Base
{
    public virtual int MyInt { get; set; }
}

public class Child : Base
{
    private int anotherInt;

    public override int MyInt
    {
        get { return anotherInt; }
        set { anotherInt = value; }
    }
}

enter image description here

Как вы можете видеть, поле поддержки существует в классе Base.. Однако он является закрытым, поэтому вы не можете получить доступ к нему из класса Child:

.field private int32 '<MyInt>k__BackingField'

И ваше свойство Child.MyInt не использует это поле. Свойство IL:

.method public hidebysig specialname virtual 
    instance int32 get_MyInt () cil managed 
{
    // Method begins at RVA 0x2109
    // Code size 7 (0x7)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: ldfld int32 ConsoleApplication2.Child::anotherInt
    IL_0006: ret
} // end of method Child::get_MyInt

.method public hidebysig specialname virtual 
    instance void set_MyInt (
        int32 'value'
    ) cil managed 
{
    // Method begins at RVA 0x2111
    // Code size 8 (0x8)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: ldarg.1
    IL_0002: stfld int32 ConsoleApplication2.Child::anotherInt
    IL_0007: ret
} // end of method Child::set_MyInt

Использует поле anotherInt, как вы могли ожидать.

Единственными способами доступа к '<MyInt>k__BackingField' (косвенно, через свойство Base.MyInt) являются:

  • Base.MyInt из класса Child

Ответ 2

Это не просто эквивалентно его фактической реализации. Компилятор перезаписывает ваши автоматические свойства на этапе прекомпиляции. Хотя имя поля будет называться чем-то другим.

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

Да, скрытое поле будет существовать, но оно не будет назначено, потому что ваше переопределение не вызывает базовую реализацию.

если вы изменили переопределение на

public override int MyInt
{
  get { return someVar; }
  set { 
    someVar = value;
    base.MyInt = value
  }
}

Тогда распределение произойдет

Ответ 3

Да, точно так же, как если бы он не был определен как автоматическое свойство.

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

Если у вас есть базовый и производный класс, определенные как:

public class Base
{
  public virtual string Name {get; set;}
}

public class Derived : Base
{
  private string _name;

  public override string Name 
  {
    get { 
      return _name; 
    }
    set 
    { 
      //access the base property we are overriding
      base.Name = value + " from derived";
      _name = value;
    }
  }
}

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

Type tbase = typeof(Base);
FieldInfo fi = tbase.GetField("<Name>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance);

Base b = new Base {Name = "Test"};

string baseValue = fi.GetValue(b).ToString();
Console.WriteLine(baseValue); //gives "Test";

Derived d = new Derived {Name = "Test" };

string derivedValue = fi.GetValue(d).ToString();
Console.WriteLine(derivedValue); //gives "Test from derived";

Имя фактического поля поддержки - это недокументированная деталь реализации, поэтому я не буду использовать ее в любом производственном коде. (Я получил его, используя LINQPad IL View)

Ответ 4

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

обновлен, так как я неправильно понял часть вопроса. Спасибо @PVitt за указание.