是否有可能让函数返回一个类而不是一个对象?

时间:2015-03-17 16:40:42

标签: .net vb.net

我正在尝试使用共享函数创建一个类,该类将返回一个基于参数值的类,而不是类实例(基本上是类工厂)。然后,我将调用类的构造函数来获取我需要的实例。

例如,我有这三个类:

class Test
  sub New(byval anID as Integer)
  end sub
end class

class Test_A
  inherits Test

  sub New(byval anID as Integer)
  end sub
end class

class Test_B
  inherits Test

  sub New(byval anID as Integer)
  end sub
end class

我想要的东西(我知道它不起作用):

class TestFactory
  shared function Create(byval aParam as Integer) as Test
    select aParam
      case 0
        return Test_A
      case 1
        return Test_B
      ...
    End Select
  end function
end class

稍后以下列方式使用它:

dim aTest as Test = New TestFactory.Create(0)(anID:=100)

我搜索了类似的问题,他们似乎都建议使用泛型。但在我的情况下,我认为它们不合适,因为我需要事先知道这门课程(见answer。)

有什么建议吗?

2 个答案:

答案 0 :(得分:2)

我很惊讶我无法直接使用构造函数,但你至少可以返回一个委托/ lambda表达式来调用你想要的构造函数:

Class TestFactory
  Public Shared Function Create(byval aParam as Integer) as Func(Of Integer, Test)
    Select aParam
      Case 0
        return Function(id) New Test_A(id)
      Case 1
        Return Function(id) New Test_B(id)
      ...
    End Select
  End Function
End Class

然后你可以像你描述的那样完全调用它:

Dim aTest As Test = TestFactory.Create(0)(100)

我们现在正在做的是Currying您的测试工厂。

但是,我的经验是,这首先是错误的方向。 Create()方法通常返回实例,而不是类型,对或错,在使用该类型并熟悉模式的其他程序员中会有这种期望。如果你沿着这条路走下去,至少要考虑一个不同的方法名称。

答案 1 :(得分:1)

在示例中,您可以将构造函数参数传递给工厂方法:

class TestFactory
  shared function Create(byval aParam as Integer, byval anID as Integer) as Test
    select aParam
      case 0
        return New Test_A(anID)
      case 1
        return New Test_B(anID)
      ...
    End Select
  end function
end class

否则,我认为你必须返回Type并使用反射来调用构造函数,这不是很好,因为正如注释中所提到的,方法签名并不能保证返回的类型是Test的子类型。

class TestFactory
  shared function Create(byval aParam as Integer) as Type
    select aParam
      case 0
        return GetType(Test_A)
      case 1
        return GetType(Test_B)
      ...
    End Select
  end function
end class

' Use something like this...
Dim t As Type = TestFactory.Create(0)
' Probably need a DirectCast here...
Dim myTest As Test = t.GetConstructor(New Type() {GetType(Integer)}) _
    .Invoke(New Object() {anID})