Why does an overridden get-only property stay null when set in base class constructor?
up vote
38
down vote
favorite
I tried the following example:
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
}
}
When I create an instance of Test, I see that ReadOnly stays null. But why?
I really do not get the hang of it, could somebody please explain to me why this happens? At least I would expect and error, that a read-only property cannot be set outside of the owning class.
c# automatic-properties
|
show 6 more comments
up vote
38
down vote
favorite
I tried the following example:
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
}
}
When I create an instance of Test, I see that ReadOnly stays null. But why?
I really do not get the hang of it, could somebody please explain to me why this happens? At least I would expect and error, that a read-only property cannot be set outside of the owning class.
c# automatic-properties
1
@SeM It's not really a duplicate, since this question is about the affect that overriding the string property is having.
– Matthew Watson
Nov 30 at 11:04
@MatthewWatson you're talking about first or second one?
– SeM
Nov 30 at 11:04
2
@SeM Both, because neither of those answers talk about overriding properties.
– Matthew Watson
Nov 30 at 11:06
2
I think it's related to that and virtual member access in constructor, no? Though it's clear if you look at how it's compiled: both classes get their own private backing field. The one in the child class gets returned. sharplab.io/…
– pinkfloydx33
Nov 30 at 11:07
2
For bonus points, addConsole.WriteLine(ReadOnly);
in the base constructor, after assigning to the property.
– Lasse Vågsæther Karlsen
Nov 30 at 11:34
|
show 6 more comments
up vote
38
down vote
favorite
up vote
38
down vote
favorite
I tried the following example:
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
}
}
When I create an instance of Test, I see that ReadOnly stays null. But why?
I really do not get the hang of it, could somebody please explain to me why this happens? At least I would expect and error, that a read-only property cannot be set outside of the owning class.
c# automatic-properties
I tried the following example:
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
}
}
When I create an instance of Test, I see that ReadOnly stays null. But why?
I really do not get the hang of it, could somebody please explain to me why this happens? At least I would expect and error, that a read-only property cannot be set outside of the owning class.
c# automatic-properties
c# automatic-properties
edited Nov 30 at 11:07
asked Nov 30 at 10:49
apfelstrudel24
19316
19316
1
@SeM It's not really a duplicate, since this question is about the affect that overriding the string property is having.
– Matthew Watson
Nov 30 at 11:04
@MatthewWatson you're talking about first or second one?
– SeM
Nov 30 at 11:04
2
@SeM Both, because neither of those answers talk about overriding properties.
– Matthew Watson
Nov 30 at 11:06
2
I think it's related to that and virtual member access in constructor, no? Though it's clear if you look at how it's compiled: both classes get their own private backing field. The one in the child class gets returned. sharplab.io/…
– pinkfloydx33
Nov 30 at 11:07
2
For bonus points, addConsole.WriteLine(ReadOnly);
in the base constructor, after assigning to the property.
– Lasse Vågsæther Karlsen
Nov 30 at 11:34
|
show 6 more comments
1
@SeM It's not really a duplicate, since this question is about the affect that overriding the string property is having.
– Matthew Watson
Nov 30 at 11:04
@MatthewWatson you're talking about first or second one?
– SeM
Nov 30 at 11:04
2
@SeM Both, because neither of those answers talk about overriding properties.
– Matthew Watson
Nov 30 at 11:06
2
I think it's related to that and virtual member access in constructor, no? Though it's clear if you look at how it's compiled: both classes get their own private backing field. The one in the child class gets returned. sharplab.io/…
– pinkfloydx33
Nov 30 at 11:07
2
For bonus points, addConsole.WriteLine(ReadOnly);
in the base constructor, after assigning to the property.
– Lasse Vågsæther Karlsen
Nov 30 at 11:34
1
1
@SeM It's not really a duplicate, since this question is about the affect that overriding the string property is having.
– Matthew Watson
Nov 30 at 11:04
@SeM It's not really a duplicate, since this question is about the affect that overriding the string property is having.
– Matthew Watson
Nov 30 at 11:04
@MatthewWatson you're talking about first or second one?
– SeM
Nov 30 at 11:04
@MatthewWatson you're talking about first or second one?
– SeM
Nov 30 at 11:04
2
2
@SeM Both, because neither of those answers talk about overriding properties.
– Matthew Watson
Nov 30 at 11:06
@SeM Both, because neither of those answers talk about overriding properties.
– Matthew Watson
Nov 30 at 11:06
2
2
I think it's related to that and virtual member access in constructor, no? Though it's clear if you look at how it's compiled: both classes get their own private backing field. The one in the child class gets returned. sharplab.io/…
– pinkfloydx33
Nov 30 at 11:07
I think it's related to that and virtual member access in constructor, no? Though it's clear if you look at how it's compiled: both classes get their own private backing field. The one in the child class gets returned. sharplab.io/…
– pinkfloydx33
Nov 30 at 11:07
2
2
For bonus points, add
Console.WriteLine(ReadOnly);
in the base constructor, after assigning to the property.– Lasse Vågsæther Karlsen
Nov 30 at 11:34
For bonus points, add
Console.WriteLine(ReadOnly);
in the base constructor, after assigning to the property.– Lasse Vågsæther Karlsen
Nov 30 at 11:34
|
show 6 more comments
2 Answers
2
active
oldest
votes
up vote
36
down vote
accepted
The compiler treats this as below; basically, the code in the constructor writes to the original backing field, in TestBase
. It seems that yours is not a supported scenario, but... I do wonder whether the language team have considered this case.
BTW: if you ever want to see what the compiler does with 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
}
}
}
2
And before anyone complains that "who cares, you shouldn't be doing this anyway as it gives you nothing", then consider that you can add attributes to the overridden property in the descendant, which will be combined with attributes on the property in the base class. So it does give you something, and although it's probably not a feature many uses, it might be important in serialization scenarios.
– Lasse Vågsæther Karlsen
Nov 30 at 11:24
@LasseVågsætherKarlsen I really want to send up the "Jared Signal" - kinda like the Bat Signal, but... geekier. Should I?
– Marc Gravell♦
Nov 30 at 11:26
1
Definitely, personally I feel that using virtual members in the constructor is the wrong thing to do, but the compiler doesn't explicitly warn about it and does in fact work, with all the usual documented warnings about what might break and why, so here I did actually expect the property to be assigned though I fully understand why not. Perhaps this particular scenario needs to be explicitly handled, either with a warning or actual support.
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
Though I feel that adding full support for this smells like a can of worms, but yes, I believe in knowledge and willfull decisions, so light the floodlight and let the team decide :)
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
3
There is no sane way to fix this, other than possibly adding the warning. Just try to add aConsole.WriteLine(ReadOnly);
in the base constructor, after assigning toReadOnly
and you'll see a different symptom, it will call the descendant getter, of the property we know hasn't been assigned, and thus try to printnull
. The only sane fix here, if anything, would be that compiling the descendant class should warn that you actually have two distinct property implementations.
– Lasse Vågsæther Karlsen
Nov 30 at 11:34
|
show 5 more comments
up vote
17
down vote
The easiest way to explain this is to consider what code the compiler is generating to implement this.
The base class is equivalent to this:
public class TestBase
{
public virtual string ReadOnly => _testBaseReadOnly;
public TestBase()
{
_testBaseReadOnly = "from base";
}
readonly string _testBaseReadOnly;
}
The derived class is equivalent to this:
class Test : TestBase
{
public override string ReadOnly => _testReadOnly;
readonly string _testReadOnly;
}
The important thing to note here is that the derived class has its OWN BACKING FIELD for ReadOnly
- it does NOT re-use the one from the base class.
Having realised that, it should be apparent why the overridden property is null.
It's because the derived class has its own backing field for ReadOnly
, and its constructor is not initialising that backing field.
Incidentally, if you're using Resharper
it will actually warn you that you're not setting ReadOnly
in the derived class:
"Get-only auto-property 'ReadOnly' is never assigned."
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
36
down vote
accepted
The compiler treats this as below; basically, the code in the constructor writes to the original backing field, in TestBase
. It seems that yours is not a supported scenario, but... I do wonder whether the language team have considered this case.
BTW: if you ever want to see what the compiler does with 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
}
}
}
2
And before anyone complains that "who cares, you shouldn't be doing this anyway as it gives you nothing", then consider that you can add attributes to the overridden property in the descendant, which will be combined with attributes on the property in the base class. So it does give you something, and although it's probably not a feature many uses, it might be important in serialization scenarios.
– Lasse Vågsæther Karlsen
Nov 30 at 11:24
@LasseVågsætherKarlsen I really want to send up the "Jared Signal" - kinda like the Bat Signal, but... geekier. Should I?
– Marc Gravell♦
Nov 30 at 11:26
1
Definitely, personally I feel that using virtual members in the constructor is the wrong thing to do, but the compiler doesn't explicitly warn about it and does in fact work, with all the usual documented warnings about what might break and why, so here I did actually expect the property to be assigned though I fully understand why not. Perhaps this particular scenario needs to be explicitly handled, either with a warning or actual support.
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
Though I feel that adding full support for this smells like a can of worms, but yes, I believe in knowledge and willfull decisions, so light the floodlight and let the team decide :)
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
3
There is no sane way to fix this, other than possibly adding the warning. Just try to add aConsole.WriteLine(ReadOnly);
in the base constructor, after assigning toReadOnly
and you'll see a different symptom, it will call the descendant getter, of the property we know hasn't been assigned, and thus try to printnull
. The only sane fix here, if anything, would be that compiling the descendant class should warn that you actually have two distinct property implementations.
– Lasse Vågsæther Karlsen
Nov 30 at 11:34
|
show 5 more comments
up vote
36
down vote
accepted
The compiler treats this as below; basically, the code in the constructor writes to the original backing field, in TestBase
. It seems that yours is not a supported scenario, but... I do wonder whether the language team have considered this case.
BTW: if you ever want to see what the compiler does with 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
}
}
}
2
And before anyone complains that "who cares, you shouldn't be doing this anyway as it gives you nothing", then consider that you can add attributes to the overridden property in the descendant, which will be combined with attributes on the property in the base class. So it does give you something, and although it's probably not a feature many uses, it might be important in serialization scenarios.
– Lasse Vågsæther Karlsen
Nov 30 at 11:24
@LasseVågsætherKarlsen I really want to send up the "Jared Signal" - kinda like the Bat Signal, but... geekier. Should I?
– Marc Gravell♦
Nov 30 at 11:26
1
Definitely, personally I feel that using virtual members in the constructor is the wrong thing to do, but the compiler doesn't explicitly warn about it and does in fact work, with all the usual documented warnings about what might break and why, so here I did actually expect the property to be assigned though I fully understand why not. Perhaps this particular scenario needs to be explicitly handled, either with a warning or actual support.
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
Though I feel that adding full support for this smells like a can of worms, but yes, I believe in knowledge and willfull decisions, so light the floodlight and let the team decide :)
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
3
There is no sane way to fix this, other than possibly adding the warning. Just try to add aConsole.WriteLine(ReadOnly);
in the base constructor, after assigning toReadOnly
and you'll see a different symptom, it will call the descendant getter, of the property we know hasn't been assigned, and thus try to printnull
. The only sane fix here, if anything, would be that compiling the descendant class should warn that you actually have two distinct property implementations.
– Lasse Vågsæther Karlsen
Nov 30 at 11:34
|
show 5 more comments
up vote
36
down vote
accepted
up vote
36
down vote
accepted
The compiler treats this as below; basically, the code in the constructor writes to the original backing field, in TestBase
. It seems that yours is not a supported scenario, but... I do wonder whether the language team have considered this case.
BTW: if you ever want to see what the compiler does with 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
}
}
}
The compiler treats this as below; basically, the code in the constructor writes to the original backing field, in TestBase
. It seems that yours is not a supported scenario, but... I do wonder whether the language team have considered this case.
BTW: if you ever want to see what the compiler does with 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
}
}
}
answered Nov 30 at 11:18
Marc Gravell♦
773k19021232538
773k19021232538
2
And before anyone complains that "who cares, you shouldn't be doing this anyway as it gives you nothing", then consider that you can add attributes to the overridden property in the descendant, which will be combined with attributes on the property in the base class. So it does give you something, and although it's probably not a feature many uses, it might be important in serialization scenarios.
– Lasse Vågsæther Karlsen
Nov 30 at 11:24
@LasseVågsætherKarlsen I really want to send up the "Jared Signal" - kinda like the Bat Signal, but... geekier. Should I?
– Marc Gravell♦
Nov 30 at 11:26
1
Definitely, personally I feel that using virtual members in the constructor is the wrong thing to do, but the compiler doesn't explicitly warn about it and does in fact work, with all the usual documented warnings about what might break and why, so here I did actually expect the property to be assigned though I fully understand why not. Perhaps this particular scenario needs to be explicitly handled, either with a warning or actual support.
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
Though I feel that adding full support for this smells like a can of worms, but yes, I believe in knowledge and willfull decisions, so light the floodlight and let the team decide :)
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
3
There is no sane way to fix this, other than possibly adding the warning. Just try to add aConsole.WriteLine(ReadOnly);
in the base constructor, after assigning toReadOnly
and you'll see a different symptom, it will call the descendant getter, of the property we know hasn't been assigned, and thus try to printnull
. The only sane fix here, if anything, would be that compiling the descendant class should warn that you actually have two distinct property implementations.
– Lasse Vågsæther Karlsen
Nov 30 at 11:34
|
show 5 more comments
2
And before anyone complains that "who cares, you shouldn't be doing this anyway as it gives you nothing", then consider that you can add attributes to the overridden property in the descendant, which will be combined with attributes on the property in the base class. So it does give you something, and although it's probably not a feature many uses, it might be important in serialization scenarios.
– Lasse Vågsæther Karlsen
Nov 30 at 11:24
@LasseVågsætherKarlsen I really want to send up the "Jared Signal" - kinda like the Bat Signal, but... geekier. Should I?
– Marc Gravell♦
Nov 30 at 11:26
1
Definitely, personally I feel that using virtual members in the constructor is the wrong thing to do, but the compiler doesn't explicitly warn about it and does in fact work, with all the usual documented warnings about what might break and why, so here I did actually expect the property to be assigned though I fully understand why not. Perhaps this particular scenario needs to be explicitly handled, either with a warning or actual support.
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
Though I feel that adding full support for this smells like a can of worms, but yes, I believe in knowledge and willfull decisions, so light the floodlight and let the team decide :)
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
3
There is no sane way to fix this, other than possibly adding the warning. Just try to add aConsole.WriteLine(ReadOnly);
in the base constructor, after assigning toReadOnly
and you'll see a different symptom, it will call the descendant getter, of the property we know hasn't been assigned, and thus try to printnull
. The only sane fix here, if anything, would be that compiling the descendant class should warn that you actually have two distinct property implementations.
– Lasse Vågsæther Karlsen
Nov 30 at 11:34
2
2
And before anyone complains that "who cares, you shouldn't be doing this anyway as it gives you nothing", then consider that you can add attributes to the overridden property in the descendant, which will be combined with attributes on the property in the base class. So it does give you something, and although it's probably not a feature many uses, it might be important in serialization scenarios.
– Lasse Vågsæther Karlsen
Nov 30 at 11:24
And before anyone complains that "who cares, you shouldn't be doing this anyway as it gives you nothing", then consider that you can add attributes to the overridden property in the descendant, which will be combined with attributes on the property in the base class. So it does give you something, and although it's probably not a feature many uses, it might be important in serialization scenarios.
– Lasse Vågsæther Karlsen
Nov 30 at 11:24
@LasseVågsætherKarlsen I really want to send up the "Jared Signal" - kinda like the Bat Signal, but... geekier. Should I?
– Marc Gravell♦
Nov 30 at 11:26
@LasseVågsætherKarlsen I really want to send up the "Jared Signal" - kinda like the Bat Signal, but... geekier. Should I?
– Marc Gravell♦
Nov 30 at 11:26
1
1
Definitely, personally I feel that using virtual members in the constructor is the wrong thing to do, but the compiler doesn't explicitly warn about it and does in fact work, with all the usual documented warnings about what might break and why, so here I did actually expect the property to be assigned though I fully understand why not. Perhaps this particular scenario needs to be explicitly handled, either with a warning or actual support.
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
Definitely, personally I feel that using virtual members in the constructor is the wrong thing to do, but the compiler doesn't explicitly warn about it and does in fact work, with all the usual documented warnings about what might break and why, so here I did actually expect the property to be assigned though I fully understand why not. Perhaps this particular scenario needs to be explicitly handled, either with a warning or actual support.
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
Though I feel that adding full support for this smells like a can of worms, but yes, I believe in knowledge and willfull decisions, so light the floodlight and let the team decide :)
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
Though I feel that adding full support for this smells like a can of worms, but yes, I believe in knowledge and willfull decisions, so light the floodlight and let the team decide :)
– Lasse Vågsæther Karlsen
Nov 30 at 11:27
3
3
There is no sane way to fix this, other than possibly adding the warning. Just try to add a
Console.WriteLine(ReadOnly);
in the base constructor, after assigning to ReadOnly
and you'll see a different symptom, it will call the descendant getter, of the property we know hasn't been assigned, and thus try to print null
. The only sane fix here, if anything, would be that compiling the descendant class should warn that you actually have two distinct property implementations.– Lasse Vågsæther Karlsen
Nov 30 at 11:34
There is no sane way to fix this, other than possibly adding the warning. Just try to add a
Console.WriteLine(ReadOnly);
in the base constructor, after assigning to ReadOnly
and you'll see a different symptom, it will call the descendant getter, of the property we know hasn't been assigned, and thus try to print null
. The only sane fix here, if anything, would be that compiling the descendant class should warn that you actually have two distinct property implementations.– Lasse Vågsæther Karlsen
Nov 30 at 11:34
|
show 5 more comments
up vote
17
down vote
The easiest way to explain this is to consider what code the compiler is generating to implement this.
The base class is equivalent to this:
public class TestBase
{
public virtual string ReadOnly => _testBaseReadOnly;
public TestBase()
{
_testBaseReadOnly = "from base";
}
readonly string _testBaseReadOnly;
}
The derived class is equivalent to this:
class Test : TestBase
{
public override string ReadOnly => _testReadOnly;
readonly string _testReadOnly;
}
The important thing to note here is that the derived class has its OWN BACKING FIELD for ReadOnly
- it does NOT re-use the one from the base class.
Having realised that, it should be apparent why the overridden property is null.
It's because the derived class has its own backing field for ReadOnly
, and its constructor is not initialising that backing field.
Incidentally, if you're using Resharper
it will actually warn you that you're not setting ReadOnly
in the derived class:
"Get-only auto-property 'ReadOnly' is never assigned."
add a comment |
up vote
17
down vote
The easiest way to explain this is to consider what code the compiler is generating to implement this.
The base class is equivalent to this:
public class TestBase
{
public virtual string ReadOnly => _testBaseReadOnly;
public TestBase()
{
_testBaseReadOnly = "from base";
}
readonly string _testBaseReadOnly;
}
The derived class is equivalent to this:
class Test : TestBase
{
public override string ReadOnly => _testReadOnly;
readonly string _testReadOnly;
}
The important thing to note here is that the derived class has its OWN BACKING FIELD for ReadOnly
- it does NOT re-use the one from the base class.
Having realised that, it should be apparent why the overridden property is null.
It's because the derived class has its own backing field for ReadOnly
, and its constructor is not initialising that backing field.
Incidentally, if you're using Resharper
it will actually warn you that you're not setting ReadOnly
in the derived class:
"Get-only auto-property 'ReadOnly' is never assigned."
add a comment |
up vote
17
down vote
up vote
17
down vote
The easiest way to explain this is to consider what code the compiler is generating to implement this.
The base class is equivalent to this:
public class TestBase
{
public virtual string ReadOnly => _testBaseReadOnly;
public TestBase()
{
_testBaseReadOnly = "from base";
}
readonly string _testBaseReadOnly;
}
The derived class is equivalent to this:
class Test : TestBase
{
public override string ReadOnly => _testReadOnly;
readonly string _testReadOnly;
}
The important thing to note here is that the derived class has its OWN BACKING FIELD for ReadOnly
- it does NOT re-use the one from the base class.
Having realised that, it should be apparent why the overridden property is null.
It's because the derived class has its own backing field for ReadOnly
, and its constructor is not initialising that backing field.
Incidentally, if you're using Resharper
it will actually warn you that you're not setting ReadOnly
in the derived class:
"Get-only auto-property 'ReadOnly' is never assigned."
The easiest way to explain this is to consider what code the compiler is generating to implement this.
The base class is equivalent to this:
public class TestBase
{
public virtual string ReadOnly => _testBaseReadOnly;
public TestBase()
{
_testBaseReadOnly = "from base";
}
readonly string _testBaseReadOnly;
}
The derived class is equivalent to this:
class Test : TestBase
{
public override string ReadOnly => _testReadOnly;
readonly string _testReadOnly;
}
The important thing to note here is that the derived class has its OWN BACKING FIELD for ReadOnly
- it does NOT re-use the one from the base class.
Having realised that, it should be apparent why the overridden property is null.
It's because the derived class has its own backing field for ReadOnly
, and its constructor is not initialising that backing field.
Incidentally, if you're using Resharper
it will actually warn you that you're not setting ReadOnly
in the derived class:
"Get-only auto-property 'ReadOnly' is never assigned."
edited Nov 30 at 11:23
answered Nov 30 at 11:00
Matthew Watson
72k691176
72k691176
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53556028%2fwhy-does-an-overridden-get-only-property-stay-null-when-set-in-base-class-constr%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
@SeM It's not really a duplicate, since this question is about the affect that overriding the string property is having.
– Matthew Watson
Nov 30 at 11:04
@MatthewWatson you're talking about first or second one?
– SeM
Nov 30 at 11:04
2
@SeM Both, because neither of those answers talk about overriding properties.
– Matthew Watson
Nov 30 at 11:06
2
I think it's related to that and virtual member access in constructor, no? Though it's clear if you look at how it's compiled: both classes get their own private backing field. The one in the child class gets returned. sharplab.io/…
– pinkfloydx33
Nov 30 at 11:07
2
For bonus points, add
Console.WriteLine(ReadOnly);
in the base constructor, after assigning to the property.– Lasse Vågsæther Karlsen
Nov 30 at 11:34