J'ai essayé l'exemple suivant:
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
}
}
Lorsque je crée une instance de Test, je constate que ReadOnly reste null. Mais pourquoi? Je ne comprends vraiment pas ce qu'il se passe, quelqu'un pourrait-il m'expliquer, s'il vous plaît, pourquoi cela se produit? Au moins, je m'attendrais à une erreur, à savoir qu'une propriété en lecture seule ne puisse pas être définie en dehors de la classe propriétaire.
Le compilateur traite cela comme ci-dessous; En gros, le code dans le constructeur écrit dans le champ de support original , dans TestBase
. Il semble que votre scénario ne soit pas pris en charge, mais ... Je me demande si l’équipe linguistique a examiné ce cas.
BTW: si jamais vous voulez voir ce que le compilateur fait avec le code: 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
}
}
}
La meilleure façon de l'expliquer consiste à examiner le code généré par le compilateur pour l'implémenter.
La classe de base est équivalente à ceci:
public class TestBase
{
public virtual string ReadOnly => _testBaseReadOnly;
public TestBase()
{
_testBaseReadOnly = "from base";
}
readonly string _testBaseReadOnly;
}
La classe dérivée est équivalente à ceci:
class Test : TestBase
{
public override string ReadOnly => _testReadOnly;
readonly string _testReadOnly;
}
La chose importante à noter ici est que la classe dérivée a son OWN BACKING FIELD pour ReadOnly
- elle ne réutilise PAS celle de la classe de base.
Ayant réalisé cela, il devrait être évident pourquoi la propriété surchargée est null.
C'est parce que la classe dérivée a son propre champ de support pour ReadOnly
et que son constructeur n'initialise pas ce champ de support.
Incidemment, si vous utilisez Resharper
, cela vous avertira que vous ne définissez pas ReadOnly
dans la classe dérivée:
"Get-only auto-property 'ReadOnly' is never assigned."