Почему я не могу получить доступ к свойствам Internal/Friend из динамического объекта?

Сначала я собираюсь показать код 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и я получаю следующее исключение:

Открытый член 'MyProperty' для типа 'DerivedClass1' не найден.

Итак, когда я изменяю уровень доступа MyProperty в Publicкод работает как положено.

Странная часть, когда я пытаюсь использовать C# эквивалент вышеупомянутого кода на VS 2015, он работает просто отлично, но на.NET Fiddler это не так.

Вот пример C# для.NET Fiddler, где я получаю то же поведение, что и VB.NET.

Итак, я что-то не так делаю?

1 ответ

Я не могу ответить на ПОЧЕМУ этого вопроса, но я могу предоставить обходной путь.

Создать 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
Другие вопросы по тегам