Почему переопределенное свойство get-only остается нулевым, если установлено в конструкторе базового класса? - PullRequest
0 голосов
/ 30 ноября 2018

Я попробовал следующий пример:

public class TestBase
{
    public virtual string ReadOnly { get; }

    public TestBase()
    {
        ReadOnly = "from base";
    }
}

class Test : TestBase
{
    public override string ReadOnly { get; }
    public Test()
    {
        // nothing here
    }
}

Когда я создаю экземпляр Test, я вижу, что ReadOnly остается нулевым.Но почему?Я действительно не понимаю, может кто-нибудь объяснить мне, почему это происходит?По крайней мере, я ожидал бы ошибку, что свойство только для чтения не может быть установлено вне класса-владельца.

Ответы [ 2 ]

0 голосов
/ 30 ноября 2018

Компилятор обрабатывает это как показано ниже;в основном код в конструкторе записывает в original backing field, в TestBase.Кажется, ваш сценарий не поддерживается, но ... мне интересно, рассмотрела ли языковая команда этот случай.

Кстати: если вы когда-нибудь захотите узнать, что компилятор делает с кодом: sharplab.io

public class TestBase
{
    [CompilerGenerated]
    private readonly string <ReadOnly>k__BackingField; // note: not legal in "real" C#

    public virtual string ReadOnly
    {
        [CompilerGenerated]
        get
        {
            return <ReadOnly>k__BackingField; // the one in TestBase
        }
    }

    public TestBase()
    {
        <ReadOnly>k__BackingField = "from base";
    }
}
internal class Test : TestBase
{
    [CompilerGenerated]
    private readonly string <ReadOnly>k__BackingField;

    public override string ReadOnly
    {
        [CompilerGenerated]
        get
        {
            return <ReadOnly>k__BackingField; // the one in Test
        }
    }
}
0 голосов
/ 30 ноября 2018

Самый простой способ объяснить это - рассмотреть, какой код генерирует компилятор для его реализации.

Базовый класс эквивалентен этому:

public class TestBase
{
    public virtual string ReadOnly => _testBaseReadOnly;

    public TestBase()
    {
        _testBaseReadOnly = "from base";
    }

    readonly string _testBaseReadOnly;
}

Производный класс эквивалентенна это:

class Test : TestBase
{
    public override string ReadOnly => _testReadOnly;

    readonly string _testReadOnly;
}

Здесь важно отметить, что у производного класса есть СОБСТВЕННОЕ ПОЛЕЗНОЕ ПОЛОЖЕНИЕ для ReadOnly - он НЕ повторно использует класс базового класса.

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

Это потому, что у производного класса есть собственное поле поддержки для ReadOnly, и его конструктор не инициализирует это поле поддержки.

Кстати, если вы используете Resharper, он действительно предупредит вас, что вы не устанавливаете ReadOnly в производном классе:

 "Get-only auto-property 'ReadOnly' is never assigned."
...