【发布时间】:2018-04-23 11:52:22
【问题描述】:
我将首先展示 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 上,它没有。
Here's the C# example 在 .NET Fiddler 上我得到与 VB.NET 相同的行为。
那么,是不是我做错了什么?
【问题讨论】:
-
您在
Foo方法中的转换是没有意义的,因为您没有将结果分配给该类型的变量。如果你这样做,你可能会看到你想要的行为:Console.WriteLine(DirectCast(targetClass, DerivedClass1).MyProperty) -
您的 C# 和 VB 代码不等效,因为 C# 使用 VB 没有的
dynamic。您的Casted变量是 VB 中的Object类型。 -
大概,VB 中的后期绑定仅适用于
Public成员。我想这是有道理的,因为后期绑定实际上涉及由框架内的代码访问的成员,这意味着在声明该成员的程序集之外,因此Friend成员将无法访问。 C# 的dynamic不同,大概不涉及相同的外部访问。 -
@jmcilhinney 我知道我可以在直接使用
DirectCast或创建该类型的变量时访问该属性,但这不是我的问题。我想知道为什么我可以从动态对象访问它,但它是公开的,而不是当它是朋友/内部的。关于 C#dynamic关键字,AFAIK,与在 VB.NET 中使用Option Strict Off的对象相同。 -
“大概,VB 中的后期绑定仅适用于公共成员” 也许这就是原因,尽管后期绑定有时在同一个程序集中很有用。无论如何,C# 示例在所有编译器中的行为并不相同。
标签: c# .net vb.net derived-class access-levels