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

+2


source to share


5 answers


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

      

+2


source


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;
            }
        }
    }
}

      

+1


source


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.

0


source


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.

0


source


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.

0


source







All Articles