【问题标题】:Why can't Interface ReadOnly properties be overridden in VB.NET, when it is valid in C#.NET?为什么在 C#.NET 中有效时不能在 VB.NET 中覆盖 Interface ReadOnly 属性?
【发布时间】:2011-09-14 12:47:26
【问题描述】:

(这与this other question有关)

如果你定义一个接口,其中只有一个 getter 的属性(= VB.NET 中的 ReadOnly),为什么你可以在用 C# 而不是用 VB 实现类时定义 setter

我原以为它是在 .NET 级别定义的,而不是特定于语言的。

例子:对于这个接口

'VB.NET
Interface SomeInterface

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

End Interface

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

这是 C# 中的正确实现:

public class Implementer:IPublicProperty
    {
        private string _publicProperty;

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

但这在 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

2015 年 4 月 23 日更新

原来这个功能是 VB14 的一部分! 见Languages features in C# 6 and VB 14New Language Features in Visual Basic 14

ReadOnly 接口属性可以通过 ReadWrite props 实现 这清理了语言的一个古怪角落。看这个例子:

Interface I
    ReadOnly Property P As Integer
End Interface


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

以前,如果您要实现 ReadOnly 属性 I.P,那么 您还必须使用 ReadOnly 属性来实现它。现在 限制已放宽:您可以通过读/写来实现它 如果你想要的财产。这个例子碰巧用一个 读/写 autoprop,但您也可以使用带有 getter 的属性和 二传手。

【问题讨论】:

    标签: .net c#-to-vb.net vb.net-to-c#


    【解决方案1】:

    请小心假设 VB.NET 和 C# 是同一种语言,但口音不同 - 它们不是。

    因为 VB.NET 需要接口成员的实现才能具有 Implements 子句,说明它正在实现哪个成员。 C# 让您可以显式(类似于 VB.NET)或隐式(没有 VB.NET 等效项)实现接口成员。因此 实际的 C# 版本是

    public class Implementer : IPublicProperty
    {
        private string _publicProperty;
    
        string IPublicProperty.PublicProperty    // explicit implementation
        {
            get
            {
                return _publicProperty;
            }
            set
            {
                _publicProperty = value;
            }
        }
    }
    

    这个确实给出了一个错误:

    错误 CS0550:“ConsoleApplication171.Implementer.ConsoleApplication171.IPublicProperty.PublicProperty.set”添加了在接口成员“ConsoleApplication171.IPublicProperty.PublicProperty”中找不到的访问器

    【讨论】:

    • 真正困扰我的是,最后,属性只是一个访问器,据我所知,编译器最终会在 MSIL 中生成某种访问器方法,例如“myProp_Set”, “my_Prop_Get”,所以定义一个setter只会导致在实现者中“添加一个额外的方法”,这不是我所说的破坏接口......但我在这里说的可能完全错误......我有对从“高级”语言到 MSIL 的过程的了解非常有限......
    • @tsi 我认为你对 VB 的看法是正确的——我对 C# 显式接口实现的 IL 细节很模糊。从语言设计的角度来看,通常 VB 方式更倾向于防止任何错误,即使以牺牲灵活性为代价。
    • 接口中未定义的属性的显式实现应该是编译器错误。显式实现是连接到接口的“私有方法”。如果不强制转换为接口,就不能在实现类上调用它们。因此,添加的访问器将是静态无法访问的。不能从接口调用它,因为它不是接口的成员,也不能从实现类调用它,因为它是私有的。
    • 嗯,很快就应该有效了,从“VB14 中的新语言功能”roslyn.codeplex.com/discussions/571884 开始(查找“ReadOnly 接口属性可以通过 ReadWrite 道具实现”)
    【解决方案2】:

    在 .net 中,接口中只读属性的实现必须包含 getter 但不包含 setter,而读写属性的实现必须同时包含 getter 和 setter。只写属性的实现(如果定义了这样的东西)也有必要包含一个 setter 但不包含 getter。

    在C#中,如果一个类定义了一个与接口中的属性同名的公共属性,该公共属性实现了该接口所需的方法,而该类没有显式实现该接口属性,编译器会自动根据需要生成一个使用公共属性的 getter 和/或 setter 的属性。即使一个类实现了三个接口,一个具有只读属性Foo,一个具有只写属性Foo,一个具有读写属性Foo,一个公共读写属性@ 987654324@ 可用于为所有这些实现Foo 属性。

    从概念上讲,vb.net 没有理由不能提供类似的功能,并根据需要生成两个(甚至三个)不同的属性来实现接口。至少目前,如果一个 vb.net 类成员被标记为实现一个接口成员,期望是它会完美匹配该成员而无需包装。

    【讨论】:

      猜你喜欢
      • 2010-10-07
      • 1970-01-01
      • 2011-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多