为什么我无法从动态对象访问内部/好友属性?

时间:2017-11-10 09:33:20

标签: c# .net vb.net derived-class access-levels

我将首先展示VB.NET代码,因为它的C#等效行为更令人困惑(见下文)

考虑以下三个类:

Public Class BaseClass
    Private Shared Rand As New Random
    Public Shared Function CreateDerived() As BaseClass
        Return If(Rand.Next(1, 3) = 1, New DerivedClass1(), New DerivedClass2())
    End Function
End Class

Public Class DerivedClass1
    Inherits BaseClass

    Sub New()
        MyProperty = 1
    End Sub

    Friend Property MyProperty As Integer
End Class

Public Class DerivedClass2
    Inherits BaseClass

    Sub New()
        MyProperty = 2
    End Sub

    Friend Property MyProperty As Integer
End Class

现在,当我尝试做这样的事情时:

Sub Foo()
    Dim targetClass As BaseClass = BaseClass.CreateDerived()

    Dim Casted
    If TypeOf (targetClass) Is DerivedClass1 Then
        Casted = DirectCast(targetClass, DerivedClass1)
    ElseIf TypeOf (targetClass) Is DerivedClass2 Then
        Casted = DirectCast(targetClass, DerivedClass2)
    Else
        Exit Sub
    End If

    Console.WriteLine(Casted.MyProperty) 'Throws an exception.
End Sub

我似乎无法访问MyProperty,并且收到以下异常:

  

未找到“DerivedClass1”类型的公共成员“MyProperty”。

因此,当我将MyProperty的访问级别更改为Public时,代码会按预期工作。

奇怪的是,当我在VS 2015 上尝试上述代码 的C#等价物时,它运行得很好, 但是 在.NET Fiddler上,它没有。

.NET Fiddler上的

Here's the C# example,我得到的内容与VB.NET相同。

那么,有什么我做错了吗?

1 个答案:

答案 0 :(得分:0)

我无法回答这个问题的原因,但我可以提供解决方法。

创建Interface并在BaseClass中实施。然后,不是将Casted声明为Object,而是将其声明为接口,它将使用与之前相同的访问修饰符正确公开所需的属性。

以下完整示例。

Sub Foo()
    Dim targetClass As BaseClass = BaseClass.CreateDerived()

    Dim Casted As Interf
    If TypeOf (targetClass) Is DerivedClass1 Then
        Casted = DirectCast(targetClass, DerivedClass1)
    ElseIf TypeOf (targetClass) Is DerivedClass2 Then
        Casted = DirectCast(targetClass, DerivedClass2)
    Else
        Exit Sub
    End If

    Console.WriteLine(Casted.MyProperty) 'Throws an exception.
End Sub

Friend Interface Interf
    Property MyProperty As Integer
End Interface

Public Class BaseClass
    Implements Interf

    Private Shared Rand As New Random

    Friend Overridable Property MyProperty As Integer Implements Interf.MyProperty

    Public Shared Function CreateDerived() As BaseClass
        Return If(Rand.Next(1, 3) = 1, New DerivedClass1(), New DerivedClass2())
    End Function
End Class

Public Class DerivedClass1
    Inherits BaseClass

    Sub New()
        MyProperty = 1
    End Sub

    Friend Overrides Property MyProperty As Integer
End Class

Public Class DerivedClass2
    Inherits BaseClass

    Sub New()
        MyProperty = 2
    End Sub

    Friend Overrides Property MyProperty As Integer
End Class