1

I have 2 codes in vb.net and C# ( I think they are identical ) :

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

Now the last line of each code ( where the E1 function is used ) is producing a different object type :

in c# ---- the copy has ChildClass type

in vb.net .... the copy has Object type

What should I do in order that the vb.net code to produce a ChildClass type object ?

Thank you !

alex
  • 694
  • 3
  • 15
  • 35
  • Did you try casting it? – Praveen Paulose Apr 16 '15 at 17:55
  • I don't want to cast. I just want that the E1 function to return the same object type as in c# version.so I don't want to change the logic of the code in vb.net. – alex Apr 16 '15 at 17:57
  • @alex: You need to call the same `E1` function. C# is called with a very specific `T` through the magic of `dynamic`. You have nothing similar in the VB.NET version. – Ben Voigt Apr 16 '15 at 17:58
  • Possible dublicate of [VB.NET equivalent of dynamic](http://stackoverflow.com/questions/2889974/vb-net-equivalent-for-c-sharp-dynamic-with-option-strict-on) – MrPaulch Apr 16 '15 at 17:59
  • @MrPaulch: I think this code proves that all the answers to that question are wrong -- there is no exact equivalent. – Ben Voigt Apr 16 '15 at 18:01
  • @MrPaulch Can you explain where do you see the duplication here ? – alex Apr 16 '15 at 18:07
  • The problem is that there is no equivalent to `dynamic` in VB.NET. That answer is given to the question I linked to. – MrPaulch Apr 16 '15 at 21:15

2 Answers2

1

The problem is that the dynamic type in C# tries to mimic the behaviour of the value if the compiler knew its type. 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. 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
IS4
  • 11,945
  • 2
  • 47
  • 86
0

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"?

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. The same would happen if you declared child as object in C#.

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. 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.

Side note: This is actually how dynamic dispatch was commonly done in C# before the introduction of the dynamic keyword.

Heinzi
  • 167,459
  • 57
  • 363
  • 519