Почему полное свойство в C # может быть переопределено только с помощью геттера, но его все равно можно установить? - PullRequest
0 голосов
/ 16 мая 2018

Я столкнулся с поведением, которое меня удивляет.Учитывая следующие два класса:

class Parent
{
    public virtual bool Property { get; set; }
}

class Child : Parent
{
    public override bool Property { get => base.Property; }
}

Я могу написать код, подобный следующему:

Child child = new Child();
child.Property = true; // this is allowed

В среде IDE это также сбивает с толку, поскольку, хотя оно разрешает присваивание, оно также указываетчто переопределенное свойство доступно только для чтения:

enter image description here

Кроме того, это переопределение разрешено, только если я использую базовый класс 'getter:

enter image description here

Что здесь происходит?

1 Ответ

0 голосов
/ 16 мая 2018

Я возьму трещину в этом.

Похоже, что это может быть просто ошибкой в ​​Intellisense, когда он не может найти базовую реализацию авто-свойства. Код действителен и имеет смысл - вот еще один способ выразить ваш пример.

Child child = new Child();
child.SetProperty(true);

class Parent
{
    private bool _property;

    public virtual bool GetProperty() => _property;
    public virtual void SetProperty(bool value) => _property = value;
}

class Child : Parent
{
    public override bool GetProperty() => base.GetProperty();
}

С этим представлением теперь очевидно, почему переопределение GetProperty хорошо. Вот соответствующий IL для вашего кода:

Main:
IL_0000:  newobj      Child..ctor
IL_0005:  ldc.i4.1
IL_0006:  callvirt    Parent.set_Property
IL_000B:  ret

Parent.get_Property:
IL_0000:  ldarg.0
IL_0001:  ldfld       Parent.<Property>k__BackingField
IL_0006:  ret

Parent.set_Property:
IL_0000:  ldarg.0
IL_0001:  ldarg.1
IL_0002:  stfld       Parent.<Property>k__BackingField
IL_0007:  ret

Parent..ctor:
IL_0000:  ldarg.0
IL_0001:  call        System.Object..ctor
IL_0006:  ret

Child.get_Property:
IL_0000:  ldarg.0
IL_0001:  call        Parent.get_Property
IL_0006:  ret

Child..ctor:
IL_0000:  ldarg.0
IL_0001:  call        Parent..ctor
IL_0006:  ret

А вот и моя версия:

Main:
IL_0000:  newobj      Child..ctor
IL_0005:  ldc.i4.1
IL_0006:  callvirt    Parent.SetProperty
IL_000B:  ret

Parent.GetProperty:
IL_0000:  ldarg.0
IL_0001:  ldfld       Parent._property
IL_0006:  ret

Parent.SetProperty:
IL_0000:  ldarg.0
IL_0001:  ldarg.1
IL_0002:  stfld       Parent._property
IL_0007:  ret

Parent..ctor:
IL_0000:  ldarg.0
IL_0001:  call        System.Object..ctor
IL_0006:  ret

Child.GetProperty:
IL_0000:  ldarg.0
IL_0001:  call        Parent.GetProperty
IL_0006:  ret

Child..ctor:
IL_0000:  ldarg.0
IL_0001:  call        Parent..ctor
IL_0006:  ret     

Обратите внимание, что это отличается от public override bool Property { get; }, и является сокращением для указания компилятору сгенерировать одиночное переопределение getter для свойства backing с тем же именем, без упоминания о ранее существовавшем установщике. Однако кто-то, имеющий опыт работы с настоящей спецификацией, определенно сможет предложить больше информации по этому вопросу.

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