开发者

vb.net: calling constructor when using generics

开发者 https://www.devze.com 2023-02-15 17:11 出处:网络
I\'m not sure if this is possible or not. I have a number of different classes that implement interface IBar, and have constructors that take a couple of values.Rather than create a bunch of almost i

I'm not sure if this is possible or not.

I have a number of different classes that implement interface IBar, and have constructors that take a couple of values. Rather than create a bunch of almost identical method, is it possible to have a generic method that will create the appropriate constructor?

private function GetFoo(Of T)(byval p1, byval p2) as List(Of IBar)
  dim list as new List(Of IBar)

  dim foo as T

  ' a loop here for different values of x
     foo = new T(x,p1) 
     list.Add开发者_如何学C(foo)
  ' end of loop
  return list
end function

I get:

'New' cannot be used on a type parameter that does not have a 'New' constraint. 


Unfortunately not - .NET generics only allow you to constrain a generic type to have a parameterless constructor, which you can then call with New T()... you can't specify a particular set of parameters.

If you don't mind making your types mutable, you could create an interface which containing a method with the relevant parameters, make all your types implement the interface, and then constrain the type to implement that method and have a parameterless constructor, but it's not ideal.

Another option is to pass in an appropriate Func which takes x and p1 and returns a new T each time. That would certainly be easy to use from C# - not quite so easy in VB IIRC, but worth considering nevertheless.


Expanding on Jon Skeet's answer, here's a possible solution using a Func parameter:

Private Function GetFoo(Of T As IBar)(ByVal p1 As Object, ByVal p2 As Object, ctor As Func(Of Integer, Object, T)) As List(Of IBar)
    Dim list As New List(Of IBar)
    Dim foo As T
    For x = 1 To 10
        foo = ctor(x, p1)
        list.Add(foo)
    Next
    Return list
End Function

usage would be similar to

    GetFoo(1, 2, Function(i, o) New BarImpl(i, o))


It is possible to cal, a constructor even if it is not specified in generic constraints. See the example below.

    'This base class has no constructor except the default empty one
Public Class MyBaseClass

End Class

'this class inhetits MyBaseType, but it also implements a non empty constructor
Public Class MySpecializedClass
    Inherits MyBaseClass
    Public Sub New(argument As String)

    End Sub
End Class

Public Function CreateObject(Of ClassType As MyBaseClass)(argument As String) As ClassType
    'First, get the item type:
    Dim itemType As Type = GetType(ClassType)
    'Now we can use the desired constructor:
    Dim constructor As ConstructorInfo = itemType.GetConstructor(New Type() {GetType(String)})
    If constructor Is Nothing Then
        Throw New InvalidConstraintException("Constructor ""New(String)"" not found.")
    Else
        Dim result As ClassType = constructor.Invoke(New Object() {argument})
        Return result
    End If
End Function

Public Sub RunTest()
    Try
        Console.WriteLine("+----------------------------------------------------+")
        Console.WriteLine("Trying to create a instance of MyBaseClass")
        Console.WriteLine("+----------------------------------------------------+")
        Dim myobject As MyBaseClass = CreateObject(Of MyBaseClass)("string value")
        Console.WriteLine(myobject)
        Console.WriteLine("Instance of MyBaseClass created")
    Catch ex As Exception
        Console.WriteLine(ex)
    End Try
    Try
        Console.WriteLine("+----------------------------------------------------+")
        Console.WriteLine("Trying to create a instance of MySpecializedClass")
        Console.WriteLine("+----------------------------------------------------+")
        Dim myobject As MyBaseClass = CreateObject(Of MySpecializedClass)("string value")
        Console.WriteLine(myobject)
        Console.WriteLine("Instance of MySpecializedClass created")
    Catch ex As Exception
        Console.WriteLine(ex)
    End Try
End Sub


Here is my answer.

Public CreateObject(Of T)() As T
    Dim newObj = Activator.CreateInstance(GetType(T), YourParameterHere)
    Return newObj
End Function

This will give you the new object. You can pass any parameters to this function.

0

精彩评论

暂无评论...
验证码 换一张
取 消