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 !

7
  • Did you try casting it? Commented Apr 16, 2015 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. Commented Apr 16, 2015 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. Commented Apr 16, 2015 at 17:58
  • Possible dublicate of VB.NET equivalent of dynamic Commented Apr 16, 2015 at 17:59
  • @MrPaulch: I think this code proves that all the answers to that question are wrong -- there is no exact equivalent. Commented Apr 16, 2015 at 18:01

2 Answers 2

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
Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.