2011-08-22 68 views
1

我最近和vb.net一起工作并且遇到了一个带有泛型的工厂模式问题。尽管我已经解决了它,但我不知道它为什么在vb.net中不起作用。我有几年的C#经验,我有时会在c#中编写如下代码,并且没有任何问题。在c#中使用泛型的工厂模式工作,但在vb.net中不起作用,为什么?

public class GenericTest 
{ 
    public static void Test() 
    { 
     var test = Factory<TestItem>.GetTest(ProcessType.Derived); 
     test.Do(); 
    } 
} 

public class TestItem 
{ 
    public int Property1 { get; set; } 
} 

public class TestBase<T> where T: class 
{ 
    public virtual void Do() 
    { 
     Console.WriteLine(typeof(T).ToString()); 
    } 
} 

public class TestDerived : TestBase<TestItem> 
{ 
    public override void Do() 
    { 
     Console.WriteLine(typeof(TestItem).ToString()); 
    } 
} 

public class Factory<T> where T:class 
{ 
    public static TestBase<T> GetTest(ProcessType processType) 
    { 
     switch (processType) 
     { 
      case ProcessType.Derived : 
       return new TestDerived() as TestBase<T>; 
      default: 
       return new TestBase<T>(); 
     } 
    } 
} 

public enum ProcessType 
{ 
    Base, 
    Derived 
} 

但是当我将上面的代码移植到vb.net时,编译器给了我一个错误。

Public Class GenericTest 
    Public Shared Sub Test() 
     Dim test = Factory(Of TestItem).GetTest(ProcessType.Derived) 
     test.DoIt() 
    End Sub 
End Class  

Public Class TestItem 
    Public Property Property1 As Integer 
End Class 

Public Class TestBase(Of T As Class) 
    Public Overridable Sub DoIt() 
     Console.WriteLine(GetType(T).ToString()) 
    End Sub 
End Class 

Public Class TestDerived 
    Inherits TestBase(Of TestItem) 

    Public Overloads Sub DoIt() 
     Console.WriteLine(GetType(TestItem).ToString()) 
    End Sub 
End Class 

Public Class Factory(Of T As Class) 
    Public Shared Function GetTest(processType As ProcessType) As TestBase(Of T) 
     Select Case processType 
      Case VB_Sandbox.ProcessType.Derived 
       ' This line gives me a compile error saying 'cannot convert TestDerived to TestBase(Of T)' 
       Return DirectCast(New TestDerived(), TestBase(Of T)) 
      Case Else 
       Return New TestBase(Of T) 
     End Select 
    End Function 
End Class 

Public Enum ProcessType 
    Base 
    Derived 
End Enum 

因此,我介绍了下面的界面,使一切正常,这实际上解决了我的问题。

Public Class TestBase(Of T As Class) 
    Implements ITest 
    Public Overridable Sub DoIt() Implements ITest.DoIt 
     Console.WriteLine(GetType(T).ToString()) 
    End Sub 
End Class 

Public Class TestDerived 
    Inherits TestBase(Of TestItem) 

    Public Overloads Sub DoIt() 
     Console.WriteLine(GetType(TestItem).ToString()) 
    End Sub 
End Class 

Public Class Factory(Of T As Class) 
    Public Shared Function GetTest(processType As ProcessType) As ITest 
     Select Case processType 
      Case VB_Sandbox.ProcessType.Derived 
       Return DirectCast(New TestDerived(), ITest) 
      Case Else 
       Return New TestBase(Of T) 
     End Select 
    End Function 
End Class 

Public Interface ITest 
    Sub DoIt() 
End Interface 

这只是vb.net的限制吗?

回答

4

主要原因是VB中的DirectCast更像是C#(cast)运算符而不是as运算符。 C#代码工作,因为as只返回nullTestDerived不是TestBase<T>(这是任何时候TTestItem)。 DirectCast居然会失败,如果TestDerived不是TestBase(Of T),所以你看到的错误。

您可以通过使用Typeof Is construct,或使用TryCast()获得VB类似的功能。

另外,你可以让TestDerived实际上继承TestBase<T>,(因此使得TestDerived<T>),这将使一切工作,而不用两种语言铸造。

用C
+0

好吧,我知道了。为什么TestDerived需要从TestBase 继承的主要原因是在实际的代码每个派生类希望把重点放在了每个具体类做一些独特的作品,所以我花了一段日子要怎么解决。无论如何,你帮助我了解发生了什么。谢谢dlev​​。 –

2

a as T#对应于TryCast(a, T)[MSDN]在VB(未DirectCast)。

+0

是的,我现在明白了。但是,即使我改变DirectCast到TryCast上述代码'TryCast(新TestDerived(),TestBase(中T))',它仍然给了我一个编译错误:( –

相关问题