VB.net和C#中的不同对象类型

时间:2015-04-16 17:51:02

标签: c# vb.net casting

我在vb.net和C#中有2个代码(我认为它们是相同的):

C#

class ChildClass
{ }

class MyClass
{
    public ICollection<ChildClass> Children { get; set; }

public MyClass()
{
    Children = new HashSet<ChildClass>() { new ChildClass() };
}
}

T e1<T>(T entity)
    where T : class, new()
{
T copy = new T();
return copy;
   }

void Test()
{
MyClass myClass = new MyClass();
dynamic children = typeof(MyClass).GetProperty("Children").GetValue(myClass);
dynamic child = Enumerable.ElementAt(children, 0);
dynamic copy = e1(child);
} 

VB.NET

Public Class ChildClass
End Class

Public Class MyClass
    Public Property Children As ICollection(Of ChildClass) = New HashSet(Of ChildClass)
End Class

Public Function e1(Of T As {Class, New})(entity As T) As T
    Dim clone As New T()
    Return clone
End Function

Sub Main()
    Dim someClass = New MyClass
    someClass.Children.Add(New ChildClass)

    Dim el = Enumerable.ElementAt(CallByName(someClass, "Children", CallType.Get), 0
    Dim el3 = CTypeDynamic(el, GetType(ChildClass))
    Dim copy = e1(el3)
End Sub

现在每个代码的最后一行(使用E1函数)生成不同的对象类型:

在c#中,副本具有ChildClass类型

在vb.net .... 副本具有对象类型

我应该怎么做才能使vb.net代码生成一个ChildClass类型的对象?

谢谢!

2 个答案:

答案 0 :(得分:1)

问题是,如果编译器知道其类型,C#中的dynamic类型会尝试模仿值的行为。因此,将其传递给方法会在运行时从其类型中推断出类型参数。 VB.NET没有做这些事情,el3的类型为Object。解决这个问题的一种方法是删除通用参数:

Public Function e1(entity As Object) As Object
    Dim clone = Activator.CreateInstance(entity.GetType())
    Return clone
End Function

答案 1 :(得分:0)

我知道您已经接受了答案,但是,为了完整起见,我仍然想回答您的问题&#34;我如何在VB.NET中做到这一点&#34;

行为的原因是泛型是编译时功能。在编译类型中,el3的类型为Object,因此T被解析为Object。如果您在C#中将child声明为object,则会发生同样的情况。

由于VB.NET没有专用的后期绑定类型(Object既是常规类型又是后期绑定类型,如果Option Strict为Off),你将不得不求助于运行时泛型解析的反射。基本上,你可以替换

Dim copy = e1(el3)

Dim copy = Me.GetType().GetMethod("e1").MakeGenericMethod(el3.GetType()).Invoke(Me, {el3})

产生与C#代码相同的结果。

附注:这实际上是在引入dynamic关键字之前,C#中通常会动态调度的方式。