2012-01-26 4 views
2

코드에서 반복이 싫은 경향이 있으므로 유일한 유형이 제네릭을 사용하는 경향이있는 문제를 발견 할 때. C++ 배경에서 나는 vb.net의 버전이 오히려 실망 스럽다는 것을 안다. C++에는 템플릿 전문화가 있으며 vb.net은 그렇지 않다는 것을 알고있다. 그래서 유형에 관계없이 정확히 동일한 코드를 수행하는 루틴 세트가있다. 통과했다. 나는 오직 일상, 문자열과 정수 무엇을 그 루틴이 문자열을 함께 할 수있는 두 가지 유형을 전달하고이vb.net specilized/overloaded generics

Public Sub decision(Of T)(ByVal a As T, ByVal b As Integer) 
    If b > 10 then 
    gt(a) 
    Else 
    lt(a) 
    End If 
End Sub 

같은

뭔가가 정수와 함께 무엇을 다릅니다. 내가 컴파일시에만 의사 결정에 전송되는 어떤 종류의에 대한 유형을 확인 할 C++, AFAIK, C++ 대 vb.net과 좌절 곳

Public Sub gt(ByVal a As String) 
Public Sub gt(ByVal a As Integer) 

Public Sub lt(ByVal a As String) 
Public Sub lt(ByVal a As Integer) 

이입니다. 그러나, vb.net에서 나는 타입 T는 문자열 또는 정수

Error 3 Overload resolution failed because no accessible 'gt' can be called with these arguments: 
    'Public Sub gt(a As String)': Value of type 'T' cannot be converted to 'String'. 
    'Public Sub gt(a As Integer)': Value of type 'T' cannot be converted to 'Integer'. 

내가 제약 시도로 변환 할 수없는 오류가 발생 Public Sub decision(Of T As {String, Integer})(ByVal a As T, ByVal b As Integer)하지만 제약 때문에 어느 문자열 상속 클래스 할 필요가 없으며, 정수를 사용할 수 있습니다.

내 다음 솔루션 gtlt의 제네릭 버전을 추가했다 :

Public Sub lt(Of T)(ByVal a As T) 
    Debug.Fail("Not Implemented") 
End Sub 

Public Sub lt(Of T)(ByVal a As T) 
    Debug.Fail("Not Implemented") 
End Sub 

그리고 헤이! 더 이상 컴파일 오류가 발생하지 않지만 호출되는 유일한 루틴은 gtlt의 일반 버전입니다. 이전에 비추어 볼 때 오류를 변환 할 수 없다고 생각합니다. generic 루틴의 오버로드가 아닌 일반적인 문제가 발생하기 전에이 문제가 발생했습니다. 해결책을 찾지 못해서 지금 해결책을 찾을 수 없습니다.

이러한 유형의 오버로드가 가능하지 않은 것이 있습니까?

편집 : 완전한 작동 예를 Differences Between C++ Templates and C# Generics에서

Module Module1 
    Sub Main() 

     decision(1, 5) 
     decision(1, 10) 
     decision("hello world", 5) 
     decision("hello world", 10) 

    End Sub 


    Public Sub decision(Of T)(ByVal a As T, ByVal b As Integer) 
     If b > 10 Then 
     gt(a) 
     Else 
     lt(a) 
     End If 
    End Sub 

    Public Sub gt(ByVal a As String) 
     Debug.WriteLine(" gt string: " + a) 
    End Sub 
    Public Sub gt(ByVal a As Integer) 
     Debug.WriteLine(" gt integer: " + a.ToString) 
    End Sub 

    Public Sub lt(ByVal a As String) 
     Debug.WriteLine(" lt string: " + a) 
    End Sub 
    Public Sub lt(ByVal a As Integer) 
     Debug.WriteLine(" lt integer: " + a.ToString) 
    End Sub 

#If False Then 
    Public Sub gt(Of T)(ByVal a As T) 
     Debug.Fail("Not implemented") 
    End Sub 
    Public Sub lt(Of T)(ByVal a As T) 
     Debug.Fail("Not implemented") 
    End Sub 
#End If 
End Module 
+0

문제는 '결정'의 선언이 아니라 오히려 호출하는 방법 또는 클래스입니다. 우리에게 보여주십시오. 귀하의 상황은 제네릭을 필요로하지 않습니다, 당신이 원래 보여준 과부하는 좋았습니다. – Ryan

+0

이 문제를 보여준 작업 예제를 추가하면 첨부 된 코드는 오류를 변환 할 수 없으며'#if False Then'를'#If True Then '으로 변경하면 항상 제네릭 버전이 호출됩니다. – Apeiron

+0

예, 이해하지만 문제가 아닙니다. 당신은 * 실제 * 예제를 할 수 있습니까? – Ryan

답변

1

(동일 비주얼 베이직 .NET에 대한 보유는) :

는 C++ 의 모든 유형 매개 변수에 대해 유효하지 않을 수있는 코드를 할 수 있습니다 템플리트는 유형 매개 변수로 사용 된 특정 유형에 대해 점검됩니다. C#에서는 클래스의 코드가 제약 조건을 충족시키는 모든 유형에서 작동 할 수있는 방식으로 작성되어야합니다 ( ). 예제의 경우 C++에서 형식 매개 변수의 개체에 대해 산술 연산자 + 및 -를 사용하는 함수를 작성할 수 있습니다. 은 형식이 아닌 형식의 인스턴스화시 오류를 생성합니다. 이 연산자를 지원하십시오. C#에서는 이것을 허용하지 않습니다. 허용되는 유일한 언어 구문은 제약 조건에서 을 추론 할 수있는 구문입니다.

.NET Generics로 문제를 해결할 수 없습니다. 그러나 당신은 lambdas와 closure를 사용하여 논리를 반복하는 것을 피할 수 있습니다. 이것은 또한보다 자연스러운 방법이라고 생각합니다.NET :

Public Sub Decision(ByVal a As String, ByVal b As Integer) 
    Decision(b, Sub() gt(a), Sub() lt(a)) 
End Sub 

Public Sub Decision(ByVal a As Integer, ByVal b As Integer) 
    Decision(b, Sub() gt(a), Sub() lt(a)) 
End Sub 

Private Sub decision(ByVal b As Integer, ByVal gt As Action, ByVal lt As Action) 
    If b > 10 Then 
     gt() 
    Else 
     lt() 
    End If 
End Sub 

Public Sub gt(ByVal a As String) 
    Debug.WriteLine(" gt string: " + a) 
End Sub 
Public Sub gt(ByVal a As Integer) 
    Debug.WriteLine(" gt integer: " + a.ToString) 
End Sub 

Public Sub lt(ByVal a As String) 
    Debug.WriteLine(" lt string: " + a) 
End Sub 
Public Sub lt(ByVal a As Integer) 
    Debug.WriteLine(" lt integer: " + a.ToString) 
End Sub 
+0

글쎄, 제네릭을 사용하는 이유는 중복 된 코드의 양, 특히 논리 분기 코드를 줄이는 것이 었습니다. 이것이 내가 할 수있는 최선이 될 것 같은데. .NET의 어떤 버전이 람다 (lambda)에 의해 소개 되었습니까? – Apeiron

+0

Lambdas는 .NET 3.5와 함께 출시 된 VB 9/VS2008에 도입되었습니다. 그러나 대상 프레임 워크를 .NET 2.0으로 설정할 수 있습니다 (여기에 설명 된 것처럼 http://stackoverflow.com/a/1162235/953288). – tore