Why can't Interface ReadOnly properties be ove

2020-04-02 09:03发布

问题:

(this is related to this other question)

If you define an Interface where there is a Property with only a getter (= ReadOnly in VB.NET), why can you define the setter in implementing classes with C# but not with VB ?

I would have thought it was defined at .NET level, and not language-specific.

Example: for this interface

'VB.NET
Interface SomeInterface

    'the interface only say that implementers must provide a value for reading
    ReadOnly Property PublicProperty As String

End Interface

or

//C# code
interface IPublicProperty
{
    string PublicProperty { get; }
}

This is a correct implementation in C# :

public class Implementer:IPublicProperty
    {
        private string _publicProperty;

        public string PublicProperty
        {
            get
            {
                return _publicProperty;
            }
            set
            {
                _publicProperty = value;
            }
        }
    }

But this is invalid in VB.NET

Public Property PublicProperty As String Implements SomeInterface.PublicProperty
    Get
        Return _myProperty
    End Get
    Set(ByVal value As String)
        _myProperty = value
    End Set
End Property

UPDATE 2015/04/23

Turns out this feature is coming as part of VB14 ! See Languages features in C# 6 and VB 14 and New Language Features in Visual Basic 14 :

ReadOnly interface properties can be implemented by ReadWrite props This cleans up a quirky corner of the language. Look at this example:

Interface I
    ReadOnly Property P As Integer
End Interface


Class C : Implements I
    Public Property P As Integer Implements I.P
End Class

Previously, if you were implementing the ReadOnly property I.P, then you had to implement it with a ReadOnly property as well. Now that restriction has been relaxed: you can implement it with a read/write property if you want. This example happens to implement it with a read/write autoprop, but you can also use a property with getter and setter.

回答1:

Be careful assuming that VB.NET and C# are the same language spoken with a different accent - they're not.

Because VB.NET requires implementation of an interface member to have that Implements clause, saying which member it is implementing. C# lets you implement interface members explicitly (SORT OF like VB.NET), or implicitly (no VB.NET equivalent). Therefore the actual C# version of this is

public class Implementer : IPublicProperty
{
    private string _publicProperty;

    string IPublicProperty.PublicProperty    // explicit implementation
    {
        get
        {
            return _publicProperty;
        }
        set
        {
            _publicProperty = value;
        }
    }
}

and this does gives an error:

error CS0550: 'ConsoleApplication171.Implementer.ConsoleApplication171.IPublicProperty.PublicProperty.set' adds an accessor not found in interface member 'ConsoleApplication171.IPublicProperty.PublicProperty'



回答2:

In .net, it is necessary that an implementation of a read-only property in an interface include a getter but no setter, and for the implementation of a read-write property to include both a getter and a setter. It is also necessary for the implementation of a write-only property (if one defines such a thing) to include a setter but no getter.

In C#, if a class defines a public property with the same name as a property in an interface, the public property implements the methods required by that interface, and the class does not explicitly implement the interface property, the compiler will automatically generate a property which uses the getter and/or setter of the public property, as appropriate. Even if a class implements three interfaces, one with a read-only property Foo, one with a write-only property Foo, and one with a read-write property Foo, a single public read-write property Foo can be used to implement the Foo property for all of them.

Conceptually, there's no reason vb.net couldn't offer a similar feature, and generate two (or even three) different properties as required to implement interfaces. At least at present, if a vb.net class member is marked as implementing an interface member, the expectation is that it will match the member perfectly without wrapping.