简体   繁体   English

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

[英]Different object's type in VB.net and C#

I have 2 codes in vb.net and C# ( I think they are identical ) : 我在vb.net和C#中有2个代码(我认为它们是相同的):

C# 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 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

Now the last line of each code ( where the E1 function is used ) is producing a different object type : 现在,每个代码的最后一行(使用E1函数的位置)正在产生不同的对象类型:

in c# ---- the copy has ChildClass type 在C#中- 副本具有ChildClass类型

in vb.net .... the copy has Object type 在vb.net中.... 副本具有对象类型

What should I do in order that the vb.net code to produce a ChildClass type object ? 为了使vb.net代码生成ChildClass类型的对象,我应该怎么做?

Thank you ! 谢谢 !

The problem is that the dynamic type in C# tries to mimic the behaviour of the value if the compiler knew its type. 问题在于,如果编译器知道值的类型,则C#中的dynamic类型会尝试模仿该值的行为。 Therefore, passing it to a method infers the type arguments from its type at run-time. 因此,将其传递给方法会在运行时从其类型推断出类型实参。 VB.NET doesn't do such things, el3 is of type Object . VB.NET不会做这些事情, el3Object类型的。 One way you can solve it is to remove the generic parameters: 解决问题的一种方法是删除通用参数:

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

I know that you have already accepted an answer, but, for completeness, I'd still like to answer your question "How can I do this in VB.NET" ? 我知道您已经接受了答案,但是出于完整性考虑,我仍然想回答您的问题“如何在VB.NET中做到这一点”

The reason for the behaviour is that generics are a compile-time feature . 出现这种情况的原因是泛型是编译时功能 At compile-type, the type of el3 is Object , so T is resolved as Object . 在compile-type处, el3的类型为Object ,因此T解析为Object The same would happen if you declared child as object in C#. 如果在C#中将child声明为object ,也会发生同样的情况。

Since VB.NET does not have a dedicated late-binding type ( Object serves as both a regular type as well as a late-binding type if Option Strict is Off), you will have to resort to reflection for run-time generics resolution. 由于VB.NET没有专用的后期绑定类型(如果Option Strict为Off,则Object既充当常规类型又充当后期绑定类型),因此对于运行时泛型解析,您将不得不依靠反射。 Basically, you can replace 基本上,您可以更换

Dim copy = e1(el3)

with

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

which yields the same result as your C# code. 产生的结果与您的C#代码相同。

Side note: This is actually how dynamic dispatch was commonly done in C# before the introduction of the dynamic keyword. 旁注:实际上,这是在引入dynamic关键字之前在C#中通常进行动态分配的方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM