C # vb.net property overcoming mechanism
I have a class in vb.net like
Public Class Customer
Private _Name As String
Public Overridable Property Name() As String
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
End Class
and the class deriving from it
Public Class ProxyCustomer
Inherits Customer
Private _name As String
Public Overrides WriteOnly Property Name() As String
Set(ByVal value As String)
_name = value
End Set
End Property
End Class
which gives me the following error Public Overridable Property Name () As String 'cannot override' Public Overridable Property Name () As String 'because they are different "ReadOnly" or "WriteOnly"
but I have the same construction in C #
public class Customer
{
public virtual string FirstName { get; set; }
}
Public class CustomerProxy: Customer {
public override string FirstName
{
set
{
base.FirstName = value;
}
}
}
which works, so firstly it is consistent with the 2 languages behaving very inconsistently.
secondly when i do reflection to get a property like
Dim propInfo = GetType(Customer).GetProperty("Name")
the propINfo.canRead property is always false, shouldn't that be true since the base class implements the getter property?
many thanks
source to share
I'll talk about the second part first. In your current vb.net code, the derived Name property replaces the original for the reflection lookup. So the reflection code only sees the version of the property WriteOnly
. Even worse, you are completely replacing the storage in your derived setter, so your getter is checking for a completely different variable than the one you set.
Regarding the first question, when overriding properties in vb.net, you should always override both the getter and the setter, even if you just replace it with an identical implementation:
The code should look like this:
Public Class ProxyCustomer
Inherits Customer
Public Overrides Property Name() As String
Get
Return MyBase.Name ''# Return the original parent property value
End Get
Set(ByVal value As String)
MyBase.Name = value
End Set
End Property
End Class
source to share
I'm a little surprised by this, since apparently, according to Joel , this is actually how it should work.
In my mind, however, it looks like this: "Property X can be read even if you redefined it in the descendant class and only implemented the setter, but reflection says no, you cannot read it."
This, to me, looks inconsistent. "Yes, you can read from a property using regular C # code, but no, reflection won't tell you that you can and can't read it."
Here is a sample code snippet. In code reports:
Base.Value.CanRead: True
Base.Value.CanWrite: True
Derived.Value.CanRead: False
Derived.Value.CanWrite: True
Setting via Derived.Value
Derived.Value: Test
(reflection get crashes with method Get not found, so commented it out)
Setting via Derived.Value
Base.Value: Test2
Note that even when writing through the Value property to Base (when I have a Derived instance) it still goes through the overridden property.
and the code:
using System;
using System.Reflection;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
Type type = typeof(Base);
PropertyInfo prop = type.GetProperty("Value");
Console.Out.WriteLine("Base.Value.CanRead: " + prop.CanRead);
Console.Out.WriteLine("Base.Value.CanWrite: " + prop.CanWrite);
type = typeof(Derived);
prop = type.GetProperty("Value");
Console.Out.WriteLine("Derived.Value.CanRead: " + prop.CanRead);
Console.Out.WriteLine("Derived.Value.CanWrite: " + prop.CanWrite);
Derived d = new Derived();
d.Value = "Test";
Console.Out.WriteLine("Derived.Value: " + d.Value);
// Console.Out.WriteLine("Reflected value: " + prop.GetValue(d, null));
Base b = new Derived();
b.Value = "Test2";
Console.In.ReadLine();
}
}
public class Base
{
public virtual String Value { get; set; }
}
public class Derived : Base
{
public override string Value
{
set
{
Console.Out.WriteLine("Setting via Derived.Value");
base.Value = value;
}
}
}
}
source to share
The two (C # and vb) derived classes you posted are not equivalent. To try and get the same behavior ( won't compile ):
public override string FirstName
{
protected get { return base.FirstName};
set
{
base.FirstName = value;
}
}
You will get "Override accessor .... cannot change accessor rights". What actually happens is that you only override the accessory.
source to share
Here is an excerpt from 10.6.3 Virtual, Private, Overridden and Abstract Accessors :
An overridden property declaration must specify the exact modifiers, type, and accessibility name as an inherited property. If an inherited property has only one accessor (that is, if the inherited property is read-only or write-only), the overriding property must include only that accessor. If the inherited property includes both accessors (that is, if the inherited property is read-write), the overriding property can include either one accessor or both.
So C # is acting as expected.
source to share
In C #, a single property declaration can generate read-only, write-only, and / or read-write properties required to satisfy any virtual property overrides or interface implementation. For example, if the property is necessary for the implementation of the interface read-only and read-write, the compiler will generate a read-only property that ignores any set
, included in the code, and read-write property, which uses both get
, and so set
. If the property overrides the read-write property but leaves the value undefined, get
orset
, the undefined operation will be bound to the one defined in the parent. This behavior differs from VB.NET, in which each property declaration will create exactly the type of property it specifies.
source to share