오버로드된 메서드 확인

실제로 오버로드 확인을 결정하는 규칙은 제공된 실제 인수에 "가장 가까운" 오버로드를 찾기 위한 것입니다. 매개 변수 형식이 인수 형식과 일치하는 메서드가 있는 경우 해당 메서드는 분명히 가장 가깝습니다. 이 경우 모든 매개 변수 형식이 다른 메서드의 매개 변수 형식보다 좁거나 같은 경우 한 메서드가 다른 메서드보다 가깝습니다. 두 메서드의 매개 변수가 다른 매개 변수보다 좁지 않은 경우 인수에 더 가까운 메서드를 확인할 방법이 없습니다.

메모. 오버로드 확인은 메서드의 예상 반환 형식을 고려하지 않습니다.

또한 명명된 매개 변수 구문으로 인해 실제 및 공식 매개 변수의 순서는 동일하지 않을 수 있습니다.

메서드 그룹이 지정된 경우 인수 목록에 대한 그룹에서 가장 적용 가능한 메서드는 다음 단계를 사용하여 결정됩니다. 특정 단계를 적용한 후 집합에 멤버가 남아 있지 않으면 컴파일 시간 오류가 발생합니다. 집합에 멤버가 하나만 남아 있으면 해당 멤버가 가장 적용 가능한 멤버입니다. 단계는 다음과 같습니다.

  1. 먼저 형식 인수가 제공되지 않은 경우 형식 매개 변수가 있는 메서드에 형식 유추를 적용합니다. 메서드에 대해 형식 유추가 성공하면 유추된 형식 인수가 해당 특정 메서드에 사용됩니다. 메서드에 대한 형식 유추가 실패하면 해당 메서드가 집합에서 제거됩니다.

  2. 다음으로, 액세스할 수 없거나 적용할 수 없는 집합의 모든 멤버( 인수 목록에 대한 섹션 적용 가능성)를 인수 목록으로 제거합니다.

  3. 다음으로 하나 이상의 인수 AddressOf 가 람다 식인 경우 아래와 같이 각 인수에 대한 대리자 이완 수준을 계산합니다. 최악의(가장 낮은) 대리자 이완 수준이 가장 낮은 대리자 이완 수준 NM보다 더 나쁜 경우 집합에서 제거 N 합니다. 대리자 이완 수준은 다음과 같습니다.

    1. 오류 대리자 이완 수준 ( 또는 람다를 AddressOf 대리자 형식으로 변환할 수 없는 경우)

    2. 반환 형식 또는 매개 변수의 대리자 이완 축소 - 인수가 AddressOf 선언된 형식을 가진 람다이고 반환 형식에서 대리자 반환 형식으로의 변환이 좁혀지는 경우 또는 인수가 일반 람다이고 해당 반환 식에서 대리자 반환 형식으로의 변환이 좁혀지는 경우 또는 인수가 비동기 람다이고 대리자 반환 형식이 Task(Of T) 해당 반환 식 T 에서 축소로 변환되는 경우 또는 인수가 반복기 람다 및 대리자 반환 형식 IEnumerator(Of T) 이거나 IEnumerable(Of T) 해당 수율 피연산자에서 축소로 T 변환되는 경우

    3. 대리자 형식이 있는 경우 또는 서명 없이 대리자를 위임하도록 대리자 이완 확대System.DelegateSystem.MultiCastDelegateSystem.Object

    4. 드롭 반환 또는 인수 대리자 이완 - 인수가 AddressOf 선언된 반환 형식을 가진 람다이거나 대리자 형식에 반환 형식이 없는 경우 또는 인수가 하나 이상의 반환 식이 있는 람다이고 대리자 형식에 반환 형식이 없는 경우 또는 인수 AddressOf 가 매개 변수가 없고 대리자 형식에 매개 변수가 있는 람다인 경우입니다.

    5. 반환 형식의 대리자 이완 확대 - 인수가 AddressOf 선언된 반환 형식을 가진 람다이고 해당 반환 형식에서 대리자의 형식으로 확대 변환이 있는 경우 또는 인수가 모든 반환 식에서 대리자 반환 형식으로의 변환이 확대되거나 하나 이상의 확장이 있는 ID인 일반 람다인 경우 또는 인수가 비동기 람다이고 대리 Task(Of T)Task 자가 및 모든 반환 식 T/Object 에서 각각으로의 변환은 하나 이상의 확대를 사용하여 확장 또는 ID입니다. 또는 인수가 반복기 람다이고 대리 IEnumerable(Of T)IEnumerableIEnumerator(Of T)IEnumerator 자가 또는 또는 모든 반환 식 T/Object 에서 하나 이상의 확대로의 변환이 확대 또는 ID인 경우.

    6. ID 대리자 이완 - 인수가 AddressOf 매개 변수나 반환 또는 수율의 확대 또는 축소 또는 삭제 없이 대리자를 정확히 일치시키는 람다인 경우입니다. 다음으로, 집합의 일부 멤버가 인수에 적용할 수 있도록 축소 변환을 요구하지 않는 경우 해당되는 모든 멤버를 제거합니다. 다음은 그 예입니다.

    Sub f(x As Object)
    End Sub
    
    Sub f(x As Short)
    End Sub
    
    Sub f(x As Short())
    End Sub
    
    f("5") ' picks the Object overload, since String->Short is narrowing
    f(5)   ' picks the Object overload, since Integer->Short is narrowing
    f({5}) ' picks the Object overload, since Integer->Short is narrowing
    f({})  ' a tie-breaker rule subsequent to [3] picks the Short() overload
    
    
  4. 다음으로, 다음과 같이 축소에 따라 제거가 수행됩니다. (Option Strict가 켜진 경우 축소가 필요한 모든 멤버는 이미 적용할 수 없는 것으로 판단되고( 인수 목록에 대한 섹션 적용 가능성) 2단계에서 제거되었습니다.)

    1. 집합의 일부 인스턴스 멤버에 인수 식 형식 Object이 있는 축소 변환만 필요한 경우 다른 모든 멤버를 제거합니다.
    2. 집합에 범위를 좁혀 Object야 하는 멤버가 두 개 이상 포함된 경우 호출 대상 식은 런타임에 바인딩된 메서드 액세스로 재분류되고 메서드 그룹이 포함된 형식이 인터페이스이거나 해당 멤버 중 하나가 확장 멤버인 경우 오류가 발생합니다.
    3. 숫자 리터럴에서만 축소해야 하는 후보가 있는 경우 아래 단계에 따라 나머지 모든 후보 중에서 가장 구체적인 후보를 선택합니다. 승자가 숫자 리터럴에서만 축소해야 하는 경우 오버로드 확인의 결과로 선택됩니다. 그렇지 않으면 오류입니다.

    메모. 이 규칙의 근거는 프로그램이 느슨하게 형식화된 경우(즉, 대부분의 변수 또는 모든 변수가 로 Object선언됨) 많은 변환이 Object 축소될 때 오버로드 확인이 어려울 수 있다는 것입니다. 오버로드 확인이 많은 상황에서 실패하도록 하는 대신(메서드 호출에 대한 인수를 강력하게 입력해야 하는 경우) 런타임까지 호출할 적절한 오버로드된 메서드를 확인합니다. 이렇게 하면 느슨한 형식의 호출이 추가 캐스트 없이 성공할 수 있습니다. 그러나 이로 인한 부작용은 런타임에 바인딩된 호출을 수행하려면 호출 대상을 캐스팅해야 한다는 것입니다 Object. 구조체 값의 경우 이 값은 임시로 박스되어야 함을 의미합니다. 결국 호출된 메서드가 구조체의 필드를 변경하려고 하면 메서드가 반환되면 이 변경 내용이 손실됩니다. 런타임 클래스 또는 구조체 형식의 멤버에 대해 런타임 바인딩이 항상 확인되므로 인터페이스는 이 특수 규칙에서 제외됩니다. 이는 구현하는 인터페이스의 멤버와 이름이 다를 수 있습니다.

  5. 다음으로, 축소할 필요가 없는 인스턴스 메서드가 집합에 남아 있는 경우 집합에서 모든 확장 메서드를 제거합니다. 다음은 그 예입니다.

    Imports System.Runtime.CompilerServices
    
    Class C3
        Sub M1(d As Integer)
        End Sub
    End Class
    
    Module C3Extensions
        <Extension> _
        Sub M1(c3 As C3, c As Long)
        End Sub
    
        <Extension> _
        Sub M1(c3 As C3, c As Short)
        End Sub
    End Module
    
    Module Test
        Sub Main()
            Dim c As New C3()
            Dim sVal As Short = 10
            Dim lVal As Long = 20
    
            ' Calls C3.M1, since C3.M1 is applicable.
            c.M1(sVal)
    
            ' Calls C3Extensions.M1 since C3.M1 requires a narrowing conversion
            c.M1(lVal)
        End Sub
    End Module
    

    메모. 가져오기(새 확장 메서드를 범위로 가져올 수 있음)를 추가해도 기존 인스턴스 메서드에 대한 호출이 확장 메서드에 다시 바인딩되지 않도록 보장하는 적용 가능한 인스턴스 메서드가 있는 경우 확장 메서드는 무시됩니다. 일부 확장 메서드(예: 인터페이스 및/또는 형식 매개 변수에 정의된 메서드)의 광범위한 범위를 고려할 때 확장 메서드에 바인딩하는 것이 더 안전합니다.

  6. 다음으로, 집합 MNM 의 두 멤버가 지정된 경우 인수 목록을 지정하는 것보다 N구체적이고(인수 목록이 지정된 멤버/형식의 섹션 특이성) 집합에서 제거 N 합니다. 둘 이상의 멤버가 집합에 남아 있고 나머지 멤버가 인수 목록을 고려할 때 동일하게 지정되지 않으면 컴파일 시간 오류가 발생합니다.

  7. 그렇지 않은 경우 집합 M 의 두 멤버를 지정하고 N다음 동률 위반 규칙을 순서대로 적용합니다.

    1. ParamArray 매개 변수가 없지만 N 그렇지 않은 경우 또는 둘 다 매개 M 변수보다 N 더 적은 인수를 ParamArray 매개 변수에 전달하는 경우 M 집합에서 제거 N 합니다. 다음은 그 예입니다.

      Module Test
          Sub F(a As Object, ParamArray b As Object())
              Console.WriteLine("F(Object, Object())")
          End Sub
      
          Sub F(a As Object, b As Object, ParamArray c As Object())
              Console.WriteLine("F(Object, Object, Object())")
          End Sub
      
         Sub G(Optional a As Object = Nothing)
            Console.WriteLine("G(Object)")
         End Sub
      
         Sub G(ParamArray a As Object())
            Console.WriteLine("G(Object())")
         End Sub    Sub Main()
              F(1)
              F(1, 2)
              F(1, 2, 3)
            G()
          End Sub
      End Module
      

      위의 예제에서는 다음 출력을 생성합니다.

      F(Object, Object())
      F(Object, Object, Object())
      F(Object, Object, Object())
      G(Object)
      

      메모. 클래스가 paramarray 매개 변수를 사용하여 메서드를 선언하는 경우 일부 확장된 폼을 일반 메서드로 포함하는 것은 드문 일이 아닙니다. 이렇게 하면 paramarray 매개 변수가 있는 메서드의 확장된 형식이 호출될 때 발생하는 배열 인스턴스의 할당을 방지할 수 있습니다.

    2. 보다 N파생된 형식으로 정의된 경우 M 집합에서 제거 N 합니다. 다음은 그 예입니다.

      Class Base
          Sub F(Of T, U)(x As T, y As U)
          End Sub
      End Class
      
      Class Derived
          Inherits Base
      
          Overloads Sub F(Of T, U)(x As U, y As T)
          End Sub
      End Class
      
      Module Test
          Sub Main()
              Dim d As New Derived()
      
              ' Calls Derived.F
              d.F(10, 10)
          End Sub
      End Module
      

      이 규칙은 확장 메서드가 정의된 형식에도 적용됩니다. 다음은 그 예입니다.

      Imports System.Runtime.CompilerServices
      
      Class Base
      End Class
      
      Class Derived
          Inherits Base
      End Class
      
      Module BaseExt
          <Extension> _
          Sub M(b As Base, x As Integer)
          End Sub
      End Module
      
      Module DerivedExt
          <Extension> _
          Sub M(d As Derived, x As Integer)
          End Sub
      End Module
      
      Module Test
          Sub Main()
              Dim b As New Base()
              Dim d As New Derived()
      
              ' Calls BaseExt.M
              b.M(10)
      
              ' Calls DerivedExt.M 
              d.M(10)
          End Sub
      End Module
      
    3. 확장 메서드이고 N 대상 형식 M 이 클래스 또는 구조이고 대상 형식 N 이 인터페이스인 경우 M 집합에서 제거 N 합니다. 다음은 그 예입니다.

      Imports System.Runtime.CompilerServices
      
      Interface I1
      End Interface
      
      Class C1
          Implements I1
      End Class
      
      Module Ext1
          <Extension> _
          Sub M(i As I1, x As Integer)
          End Sub
      End Module
      
      Module Ext2
          <Extension> _
          Sub M(c As C1, y As Integer)
          End Sub
      End Module
      
      Module Test
          Sub Main()
              Dim c As New C1()
      
              ' Calls Ext2.M, because Ext1.M is hidden since it extends
              ' an interface.
              c.M(10)
      
              ' Calls Ext1.M
              CType(c, I1).M(10)
          End Sub
      End Module
      
    4. 확장 메서드와 N 형식 매개 변수 대체 후의 대상 형식 MN 동일하고 형식 매개 변수 대체 이전의 M 대상 형식에 형식 매개 변수가 포함되지 않지만 대상 형식이 있는 경우 M 대상 형식 NN보다 형식 매개 변수가 적고 집합에서 제거 N 됩니다. 다음은 그 예입니다.

      Imports System.Runtime.CompilerServices
      
      Module Module1
          Sub Main()
              Dim x As Integer = 1
              x.f(1) ' Calls first "f" extension method
      
              Dim y As New Dictionary(Of Integer, Integer)
              y.g(1) ' Ambiguity error
          End Sub
      
          <Extension()> Sub f(x As Integer, z As Integer)
          End Sub
      
          <Extension()> Sub f(Of T)(x As T, z As T)
          End Sub
      
          <Extension()> Sub g(Of T)(y As Dictionary(Of T, Integer), z As T)
          End Sub
      
          <Extension()> Sub g(Of T)(y As Dictionary(Of T, T), z As T)
          End Sub
      End Module
      
    5. 형식 인수를 대체하기 전에 제네릭(섹션 제네릭성)이 아닌 N경우 M 집합에서 제거 N 합니다.

    6. 확장 메서드가 아니고 있는 경우 M 집합에서 제거 N 합니다.N

    7. 확장 메서드 M 이고 N 이전에 N 발견된 경우M(섹션 확장 메서드 컬렉션) 집합에서 제거 N 합니다. 다음은 그 예입니다.

      Imports System.Runtime.CompilerServices
      
      Class C1
      End Class
      
      Namespace N1
          Module N1C1Extensions
              <Extension> _
              Sub M1(c As C1, x As Integer)
              End Sub
          End Module
      End Namespace
      
      Namespace N1.N2
          Module N2C1Extensions
              <Extension> _
              Sub M1(c As C1, y As Integer)
              End Sub
          End Module
      End Namespace
      
      Namespace N1.N2.N3
          Module Test
              Sub Main()
                  Dim x As New C1()
      
                  ' Calls N2C1Extensions.M1
                  x.M1(10)
              End Sub
          End Module
      End Namespace
      

      동일한 단계에서 확장 메서드를 찾은 경우 해당 확장 메서드는 모호합니다. 확장 메서드를 포함하는 표준 모듈의 이름을 사용하여 일반 멤버인 것처럼 확장 메서드를 호출하면 항상 호출이 명확해질 수 있습니다. 다음은 그 예입니다.

      Imports System.Runtime.CompilerServices
      
      Class C1
      End Class
      
      Module C1ExtA
          <Extension> _
          Sub M(c As C1)
          End Sub
      End Module
      
      Module C1ExtB
          <Extension> _
          Sub M(c As C1)
          End Sub
      End Module
      
      Module Main
          Sub Test()
              Dim c As New C1()
      
              C1.M()               ' Ambiguous between C1ExtA.M and BExtB.M
              C1ExtA.M(c)          ' Calls C1ExtA.M
              C1ExtB.M(c)          ' Calls C1ExtB.M
          End Sub
      End Module
      
    8. N 형식 인수를 생성하기 위해 둘 다 형식 유추가 필요하고 M 형식 인수(즉, 각 형식 인수가 단일 형식으로 유추됨)에 대해 지배적 형식을 결정할 필요가 없는 N 경우 M 집합에서 제거 N 했습니다.

      메모. 이 규칙은 이전 버전에서 성공한 오버로드 확인(형식 인수에 대해 여러 형식을 유추하면 오류가 발생함)이 동일한 결과를 계속 생성하도록 합니다.

    9. 식에서 AddressOf 대리자 생성 식의 대상을 확인하기 위해 오버로드 확인이 수행되고 있는 경우 대리 M 자와 함수 모두 서브루틴인 경우 N 집합에서 제거 N 합니다. 마찬가지로 대리자와 M 하위 경로 N 가 모두 함수인 경우 집합에서 제거 N 합니다.

    10. 명시적 인수 대신 선택적 매개 변수 기본값을 사용하지 않은 N 경우 M 집합에서 제거 N 합니다.

    11. 형식 인수를 대체하기 전에 제네릭(섹션 제네릭성)의 깊이가 더 N큰 경우 M 집합에서 제거 N 합니다.

  8. 그렇지 않으면 호출이 모호하고 컴파일 시간 오류가 발생합니다.

인수 목록이 지정된 멤버/형식의 특이성

해당 서명이 같거나 각 매개 변수 형식이 해당 매개 변수 N형식 M 과 같은 경우 멤버 M 는 인수 목록이 A지정된 경우와 동일하게 특정N한 것으로 간주됩니다.

메모. 확장 메서드로 인해 두 멤버가 동일한 시그니처를 가진 메서드 그룹에서 끝날 수 있습니다. 또한 두 멤버는 형식 매개 변수 또는 paramarray 확장으로 인해 동일하게 구체적일 수 있지만 서명이 동일하지 않습니다.

멤버 M 는 서명이 다르고 하나 이상의 매개 변수 형식이 매개 변수 형식 M 보다 더 구체적이고 매개 변수 형식N이 매개 변수 M형식 N 보다 더 구체적인 경우보다 N구체적인 것으로 간주됩니다. 매개 변수 Mj 쌍이 인수 AjMjNj 일치하는 경우 형식은 다음 조건 중 하나가 true인 경우 형식 Nj 보다 더 구체적인 것으로 간주됩니다.

  • 형식에서 형식Nj으로의 Mj 확대 변환이 있습니다. (참고. 이 경우 실제 인수와 관계없이 매개 변수 형식을 비교하기 때문에 값에 맞는 상수 식에서 숫자 형식으로의 확대 변환은 고려되지 않습니다.)

  • Aj 는 리터럴 0이고 숫자 Mj 형식이며 Nj 열거형 형식입니다. (참고. 리터럴 0 이 열거형 형식으로 확장되므로 이 규칙이 필요합니다. 열거형 형식이 기본 형식으로 확장되므로 기본적으로 오버로드 해상도 0 가 숫자 형식보다 열거형 형식을 선호합니다. 이 동작이 직관에 어긋났다는 피드백을 많이 받았습니다.)

  • Mj Nj 은 숫자 형식이며 Mj 목록 , ,SByte, Short,IntegerULongSingleDoubleUIntegerDecimalUShortLong, 보다 Byte일찍 Nj 제공됩니다. (참고. 숫자 형식에 대한 규칙은 특정 크기의 부호 있는 숫자 형식과 부호 없는 숫자 형식 간에 축소 변환만 있기 때문에 유용합니다. 위의 규칙은 더 많은 "자연" 숫자 형식을 위해 두 형식 간의 동률을 끊습니다. 이는 특정 크기의 부호 있는 숫자 형식과 부호 없는 숫자 형식(예: 둘 다에 맞는 숫자 리터럴)으로 확장되는 형식에 대해 오버로드 확인을 수행할 때 특히 중요합니다.

  • Mj Nj 대리자 함수 형식이고 반환 형식은 람다 메서드로 분류되는 If AjMjNj 반환 형식보다 더 구체적이며 MjNjSystem.Linq.Expressions.Expression(Of T), 또는 형식의 형식 인수(대리자 형식이라고 가정)가 비교되는 형식으로 대체됩니다.

  • Mj 는 형식과 Aj동일하며 Nj 그렇지 않습니다. (참고. 이전 규칙은 C#과 약간 다릅니다. 즉, C#에서는 대리자 함수 형식이 반환 형식을 비교하기 전에 동일한 매개 변수 목록을 가져야 하지만 Visual Basic은 그렇지 않습니다.)

제네릭성

멤버는 다음과 같이 멤버 MN 보다 덜 제네릭으로 결정됩니다.

  1. 일치하는 매개 변수의 각 쌍에 NjMj 대해 메서드의 형식 매개 Mj 변수와 관련하여 제네릭 Nj 이 적거나 같고 메서드의 형식 매개 변수와 관련하여 하나 이상의 Mj 제네릭이 아닌 경우
  2. 그렇지 않으면 일치하는 각 매개 변수 쌍에 대해 형식 Mj 의 형식 매개 변수 MjNj와 관련하여 제네릭 Nj 이 적거나 같고 형식의 형식 매개 변수 M 와 관련하여 하나 이상의 Mj 제네릭이 아닌 경우 보다 제네릭N이 적습니다.

매개 변수 M 는 해당 형식과 Nt 둘 다 형식 Mt 매개 변수 N 를 참조하거나 둘 다 형식 매개 변수를 참조하지 않는 경우 매개 변수에 대해 동일한 제네릭으로 간주됩니다. M는 형식 매개 변수 Nt 를 참조하지 않고 참조하는 경우 Mt 보다 N 덜 제네릭인 것으로 간주됩니다.

다음은 그 예입니다.

Class C1(Of T)
    Sub S1(Of U)(x As U, y As T)
    End Sub

    Sub S1(Of U)(x As U, y As U)
    End Sub

    Sub S2(x As Integer, y As T)
    End Sub

    Sub S2(x As T, y As T)
    End Sub
End Class

Module Test
    Sub Main()
        Dim x As C1(Of Integer) = New C1(Of Integer)

        x.S1(10, 10)    ' Calls S1(U, T)
        x.S2(10, 10)    ' Calls S2(Integer, T)
    End Sub
End Module

커리링 중에 수정된 확장 메서드 형식 매개 변수는 메서드의 형식 매개 변수가 아니라 형식의 형식 매개 변수로 간주됩니다. 다음은 그 예입니다.

Imports System.Runtime.CompilerServices

Module Ext1
    <Extension> _
    Sub M1(Of T, U)(x As T, y As U, z As U)
    End Sub
End Module

Module Ext2
    <Extension> _
    Sub M1(Of T, U)(x As T, y As U, z As T)
    End Sub
End Module

Module Test
    Sub Main()
        Dim i As Integer = 10

        i.M1(10, 10)
    End Sub
End Module

제네릭의 깊이

일치하는 각 매개 변수 Mj 쌍에 대해 제네릭의 깊이가 크거나 같고 MjNj하나 이상의 제네릭 깊이가 있는 경우 멤버 M 는 멤버 N 보다 NjMj 더 큰 제네릭 깊이를 가지는 것으로 결정됩니다. 제네릭의 깊이는 다음과 같이 정의됩니다.

  • 형식 매개 변수가 아닌 다른 항목은 형식 매개 변수보다 제네릭성의 깊이가 더 큽니다.

  • 재귀적으로, 생성된 형식은 하나 이상의 형식 인수가 제네릭의 깊이가 더 크고 형식 인수가 다른 형식 인수보다 깊이가 작지 않은 경우 다른 생성된 형식(형식 인수 수가 동일한)보다 더 많은 제네릭을 가집니다.

  • 첫 번째 요소 형식의 제네릭 깊이가 두 번째 요소 형식보다 더 큰 경우 배열 형식은 다른 배열 형식(동일한 수의 차원 포함)보다 제네릭의 깊이가 더 큽니다.

다음은 그 예입니다.

Module Test

    Sub f(Of T)(x As Task(Of T))
    End Sub

    Sub f(Of T)(x As T)
    End Sub

    Sub Main()
        Dim x As Task(Of Integer) = Nothing
        f(x)            ' Calls the first overload
    End Sub
End Module

인수 목록에 적용 가능성

메서드는 인수 목록을 사용하여 메서드를 호출할 수 있는 경우 형식 인수, 위치 인수 및 명명된 인수 집합에 적용 할 수 있습니다. 인수 목록은 다음과 같이 매개 변수 목록과 일치합니다.

  1. 먼저 각 위치 인수를 메서드 매개 변수 목록과 일치합니다. 매개 변수보다 위치 인수가 더 많고 마지막 매개 변수가 paramarray가 아니면 메서드를 적용할 수 없습니다. 그렇지 않으면 paramarray 매개 변수는 paramarray 요소 형식의 매개 변수를 사용하여 위치 인수의 수와 일치하도록 확장됩니다. paramarray로 이동하는 위치 인수를 생략하면 메서드를 적용할 수 없습니다.
  2. 다음으로, 명명된 각 인수를 지정된 이름의 매개 변수와 일치합니다. 명명된 인수 중 하나가 일치하지 않거나, paramarray 매개 변수와 일치하거나, 이미 다른 위치 또는 명명된 인수와 일치하는 인수와 일치하는 경우 메서드는 적용되지 않습니다.
  3. 다음으로 형식 인수를 지정한 경우 형식 매개 변수 목록과 일치합니다. 두 목록에 동일한 수의 요소가 없으면 형식 인수 목록이 비어 있지 않으면 메서드를 적용할 수 없습니다. 형식 인수 목록이 비어 있으면 형식 유추를 사용하여 형식 인수 목록을 시도하고 유추합니다. 형식 추론에 실패하면 메서드를 적용할 수 없습니다. 그렇지 않으면 형식 인수가 서명의 형식 매개 변수 대신 채워집니다. 일치하지 않은 매개 변수가 선택 사항이 아닌 경우 메서드를 적용할 수 없습니다.
  4. 인수 식이 일치하는 매개 변수 형식으로 암시적으로 변환할 수 없는 경우 메서드를 적용할 수 없습니다.
  5. 매개 변수가 ByRef이고 매개 변수 형식에서 인수 형식으로의 암시적 변환이 없는 경우 메서드를 적용할 수 없습니다.
  6. 형식 인수가 메서드의 제약 조건(3단계에서 유추된 형식 인수 포함)을 위반하는 경우 메서드를 적용할 수 없습니다. 다음은 그 예입니다.
Module Module1
    Sub Main()
        f(Of Integer)(New Exception)
        ' picks the first overload (narrowing),
        ' since the second overload (widening) violates constraints 
    End Sub

    Sub f(Of T)(x As IComparable)
    End Sub

    Sub f(Of T As Class)(x As Object)
    End Sub
End Module

단일 인수 식이 paramarray 매개 변수와 일치하고 인수 식의 형식을 paramarray 매개 변수의 형식과 paramarray 요소 형식 모두로 변환할 수 있는 경우 이 메서드는 두 가지 예외를 제외하고 확장된 형식과 확장되지 않은 형식 모두에 적용할 수 있습니다. 인수 식의 형식에서 paramarray 형식으로의 변환이 좁혀지는 경우 메서드는 확장된 형식에만 적용할 수 있습니다. 인수 식이 리터럴 Nothing이면 메서드는 확장되지 않은 형식에만 적용할 수 있습니다. 다음은 그 예입니다.

Module Test
    Sub F(ParamArray a As Object())
        Dim o As Object

        For Each o In a
            Console.Write(o.GetType().FullName)
            Console.Write(" ")
        Next o
        Console.WriteLine()
    End Sub

    Sub Main()
        Dim a As Object() = { 1, "Hello", 123.456 }
        Dim o As Object = a

        F(a)
        F(CType(a, Object))
        F(o)
        F(CType(o, Object()))
    End Sub
End Module

위의 예제에서는 다음 출력을 생성합니다.

System.Int32 System.String System.Double
System.Object[]
System.Object[]
System.Int32 System.String System.Double

첫 번째 및 마지막 호출F에서는 인수 형식에서 매개 변수 형식(둘 다 Object()형식)으로 확대 변환이 존재하고 인수가 일반 값 매개 변수로 전달되기 때문에 일반적인 형식 F 이 적용됩니다. 두 번째 및 세 번째 호출에서는 인수 형식에서 매개 변수 형식으로의 F 확대 변환이 없기 때문에 일반적인 형식을 적용할 Object() 수 없습니다(변환에서 Object 축소됨). 그러나 확장된 형식 F 을 적용할 수 있으며 호출에 의해 하나의 요소가 Object() 만들어집니다. 배열의 단일 요소는 지정된 인수 값(그 자체가 참조)을 사용하여 Object()초기화됩니다.

인수 전달 및 선택적 매개 변수에 대한 인수 선택

매개 변수가 값 매개 변수인 경우 일치하는 인수 식을 값으로 분류해야 합니다. 값은 매개 변수의 형식으로 변환되고 런타임에 매개 변수로 전달됩니다. 매개 변수가 참조 매개 변수이고 일치하는 인수 식이 매개 변수와 동일한 형식의 변수로 분류되는 경우 런타임에 변수에 대한 참조가 매개 변수로 전달됩니다.

그렇지 않으면 일치하는 인수 식이 변수, 값 또는 속성 액세스로 분류되면 매개 변수 형식의 임시 변수가 할당됩니다. 런타임에 메서드를 호출하기 전에 인수 식이 값으로 다시 분류되고 매개 변수 형식으로 변환되고 임시 변수에 할당됩니다. 그런 다음 임시 변수에 대한 참조가 매개 변수로 전달됩니다. 메서드 호출이 평가된 후 인수 식이 변수 또는 속성 액세스로 분류되면 임시 변수가 변수 식 또는 속성 액세스 식에 할당됩니다. 속성 액세스 식에 접근자가 없 Set 으면 할당이 수행되지 않습니다.

인수가 제공되지 않은 선택적 매개 변수의 경우 컴파일러는 아래에 설명된 대로 인수를 선택합니다. 모든 경우에 제네릭 형식 대체 후 매개 변수 형식에 대해 테스트합니다.

  • 선택적 매개 변수에 특성 System.Runtime.CompilerServices.CallerLineNumber이 있고 호출이 소스 코드의 위치에서 시작되고 해당 위치의 줄 번호를 나타내는 숫자 리터럴이 매개 변수 형식으로의 기본 변환이 있는 경우 숫자 리터럴이 사용됩니다. 호출이 여러 줄에 걸쳐 있는 경우 사용할 줄의 선택은 구현에 따라 달라집니다.

  • 선택적 매개 변수에 특성 System.Runtime.CompilerServices.CallerFilePath이 있고 호출이 소스 코드의 위치이고 해당 위치의 파일 경로를 나타내는 문자열 리터럴이 매개 변수 형식으로의 기본 변환이 있는 경우 문자열 리터럴이 사용됩니다. 파일 경로의 형식은 구현에 따라 다릅니다.

  • 선택적 매개 변수에 특성 System.Runtime.CompilerServices.CallerMemberName이 있고 호출이 형식 멤버의 본문 내에 있거나 해당 형식 멤버의 모든 부분에 적용된 특성에 있고 해당 멤버 이름을 나타내는 문자열 리터럴이 매개 변수 형식으로의 기본 변환이 있는 경우 문자열 리터럴이 사용됩니다. 속성 접근자 또는 사용자 지정 이벤트 처리기의 일부인 호출의 경우 사용된 멤버 이름은 속성 또는 이벤트 자체의 이름입니다. 연산자 또는 생성자의 일부인 호출의 경우 구현별 이름이 사용됩니다.

위의 값이 적용되지 않으면 선택적 매개 변수의 기본값이 사용됩니다(또는 Nothing 기본값이 제공되지 않은 경우). 위의 항목 중 하나 이상이 적용되는 경우 사용할 선택은 구현에 따라 달라집니다.

CallerFilePath 특성은 CallerLineNumber 로깅에 유용합니다. 이 CallerMemberName 기능은 .를 구현하는 데 INotifyPropertyChanged유용합니다. 다음은 예제입니다.

Sub Log(msg As String,
        <CallerFilePath> Optional file As String = Nothing,
        <CallerLineNumber> Optional line As Integer? = Nothing)
    Console.WriteLine("{0}:{1} - {2}", file, line, msg)
End Sub

WriteOnly Property p As Integer
    Set(value As Integer)
        Notify(_p, value)
    End Set
End Property

Private _p As Integer

Sub Notify(Of T As IEquatable(Of T))(ByRef v1 As T, v2 As T,
        <CallerMemberName> Optional prop As String = Nothing)
    If v1 IsNot Nothing AndAlso v1.Equals(v2) Then Return
    If v1 Is Nothing AndAlso v2 Is Nothing Then Return
    v1 = v2
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(prop))
End Sub

위의 선택적 매개 변수 외에도 Microsoft Visual Basic은 메타데이터에서 가져온 경우(예: DLL 참조에서) 몇 가지 추가 선택적 매개 변수를 인식합니다.

  • 메타데이터에서 가져올 때 Visual Basic은 매개 변수가 선택 사항임을 나타내는 매개 변수 <Optional> 로 처리합니다. 이러한 방식으로 키워드를 사용하여 Optional 표현할 수 없더라도 선택적 매개 변수가 있지만 기본값이 없는 선언을 가져올 수 있습니다.

  • 선택적 매개 변수에 특성 Microsoft.VisualBasic.CompilerServices.OptionCompareAttribute이 있고 숫자 리터럴 1 또는 0이 매개 변수 형식으로 변환된 경우 컴파일러는 리터럴 1(유효한 경우) 또는 유효한 경우 Option Compare TextOptional Compare Binary 리터럴 0(리터럴 0)을 인수로 사용합니다.

  • 선택적 매개 변수에 특성 System.Runtime.CompilerServices.IDispatchConstantAttribute이 있고 형식 Object이 있고 기본값을 지정하지 않는 경우 컴파일러는 인수 New System.Runtime.InteropServices.DispatchWrapper(Nothing)를 사용합니다.

  • 선택적 매개 변수에 특성 System.Runtime.CompilerServices.IUnknownConstantAttribute이 있고 형식 Object이 있고 기본값을 지정하지 않는 경우 컴파일러는 인수 New System.Runtime.InteropServices.UnknownWrapper(Nothing)를 사용합니다.

  • 선택적 매개 변수에 형식 Object이 있고 기본값을 지정하지 않는 경우 컴파일러는 인수 System.Reflection.Missing.Value를 사용합니다.

조건부 메서드

호출 식이 참조하는 대상 메서드가 인터페이스의 멤버가 아닌 서브루틴이고 메서드에 하나 이상의 System.Diagnostics.ConditionalAttribute 특성이 있는 경우 식 평가는 소스 파일의 해당 시점에 정의된 조건부 컴파일 상수에 따라 달라집니다. 특성의 각 인스턴스는 조건부 컴파일 상수의 이름을 지정하는 문자열을 지정합니다. 각 조건부 컴파일 상수는 조건부 컴파일 문의 일부인 것처럼 평가됩니다. 상수가 계산 True되면 식은 런타임에 정상적으로 계산됩니다. 상수가 계산 False되면 식이 전혀 계산되지 않습니다.

특성을 찾는 경우 재정의 가능한 메서드의 가장 파생된 선언이 선택됩니다.

메모. 이 특성은 함수 또는 인터페이스 메서드에서 유효하지 않으며 어떤 종류의 메서드에 지정되어 있으면 무시됩니다. 따라서 조건부 메서드는 호출 문에만 표시됩니다.

형식 인수 유추

형식 인수를 지정하지 않고 형식 매개 변수가 있는 메서드를 호출하는 경우 형식 인수 유추 를 사용하여 호출에 대한 형식 인수를 시도하고 유추합니다. 이렇게 하면 형식 인수를 사소하게 유추할 수 있는 경우 형식 매개 변수를 사용하여 메서드를 호출하는 데 좀 더 자연스러운 구문을 사용할 수 있습니다. 예를 들어 다음과 같은 메서드 선언이 제공됩니다.

Module Util
    Function Choose(Of T)(b As Boolean, first As T, second As T) As T
        If b Then
            Return first
        Else
            Return second
        End If
    End Function
End Class

형식 인수를 명시적으로 지정하지 않고 메서드를 호출 Choose 할 수 있습니다.

' calls Choose(Of Integer)
Dim i As Integer = Util.Choose(True, 5, 213)
' calls Choose(Of String)
Dim s As String = Util.Choose(False, "a", "b") 

형식 인수 유추를 통해 형식 인수는 String 인수 Integer 에서 메서드로 결정됩니다.

형식 인수 유추는 인수 목록의 람다 메서드 또는 메서드 포인터에서 식 재분류가 수행되기 전에 발생합니다. 이러한 두 종류의 식을 다시 분류하려면 매개 변수의 형식을 알려야 할 수 있기 때문에 발생합니다. 인수 A1,...,An집합, 일치하는 매개 변수 집합 및 메서드 형식 매개 변수 P1,...,Pn 집합을 지정하면 인수와 메서드 형식 매개 T1,...,Tn변수 간의 종속성이 먼저 다음과 같이 수집됩니다.

  • 리터럴인 Nothing 경우 An 종속성이 생성되지 않습니다.

  • 람다 메서드이고 형식 Pn 이 생성된 대리자 형식이거나 System.Linq.Expressions.Expression(Of T)생성된 T 대리자 형식인 경우 An

  • 람다 메서드 매개 변수의 형식이 해당 매개 변수의 형식에서 유추되고 매개 변수 Pn형식이 메서드 형식 매개 변수 TnAn 에 따라 달라지면 종속성이 있습니다Tn.

  • 람다 메서드 매개 변수의 형식을 지정하고 해당 매개 변수의 형식이 메서드 형식 매개 변수 PnTnTn 에 종속된 경우 종속성이 있습니다.An

  • 반환 형식이 메서드 형식 Pn 매개 변수 TnTnAn에 종속된 경우 .

  • 메서드 포인터이고 형식 Pn 이 생성된 대리자 형식인 경우 An

  • 반환 형식이 메서드 형식 Pn 매개 변수 TnTnAn에 종속된 경우 .

  • 생성된 형식이고 형식 Pn 이 메서드 형식 매개 변수 TnAnTn 에 종속된 경우 .Pn

  • 그렇지 않으면 종속성이 생성되지 않습니다.

종속성을 수집한 후에는 종속성이 없는 모든 인수가 제거됩니다. 메서드 형식 매개 변수에 나가는 종속성이 없는 경우(즉, 메서드 형식 매개 변수가 인수에 종속되지 않음) 형식 유추가 실패합니다. 그렇지 않으면 나머지 인수 및 메서드 형식 매개 변수는 강력한 연결 구성 요소로 그룹화됩니다. 강력한 연결 구성 요소는 인수 및 메서드 형식 매개 변수 집합으로, 구성 요소의 모든 요소는 다른 요소에 대한 종속성을 통해 연결할 수 있습니다.

그러면 강력한 연결 구성 요소가 토폴로지로 정렬되고 토폴로지 순서로 처리됩니다.

  • 강력한 형식의 구성 요소에 하나의 요소만 포함된 경우

    • 요소가 이미 완료로 표시된 경우 건너뜁니다.

    • 요소가 인수인 경우 인수의 형식 힌트를 해당 요소에 의존하는 메서드 형식 매개 변수에 추가하고 요소를 완료로 표시합니다. 인수가 여전히 유추된 형식이 필요한 매개 변수가 있는 람다 메서드인 경우 해당 매개 변수의 형식을 유추 Object 합니다.

    • 요소가 메서드 형식 매개 변수인 경우 메서드 형식 매개 변수를 인수 형식 힌트 중에서 주요 형식으로 유추하고 요소를 완료로 표시합니다. 형식 힌트에 배열 요소 제한이 있는 경우 지정된 형식의 배열 간에 유효한 변환만 고려됩니다(즉, 공변 및 내장 배열 변환). 형식 힌트에 제네릭 인수 제한이 있는 경우 ID 변환만 고려됩니다. 주요 형식을 선택할 수 없으면 유추가 실패합니다. 람다 메서드 인수 형식이 이 메서드 형식 매개 변수에 따라 달라지면 형식이 람다 메서드로 전파됩니다.

  • 강력한 형식의 구성 요소에 둘 이상의 요소가 포함된 경우 구성 요소에 주기가 포함됩니다.

    • 구성 요소의 요소인 각 메서드 형식 매개 변수에 대해 메서드 형식 매개 변수가 완료로 표시되지 않은 인수에 종속된 경우 해당 종속성을 유추 프로세스의 끝에서 검사할 어설션으로 변환합니다.

    • 강력한 형식의 구성 요소가 결정된 지점에서 유추 프로세스를 다시 시작합니다.

모든 메서드 형식 매개 변수에 대해 형식 유추가 성공하면 어설션으로 변경된 모든 종속성이 확인됩니다. 인수 형식을 메서드 형식 매개 변수의 유추된 형식으로 암시적으로 변환할 수 있는 경우 어설션이 성공합니다. 어설션이 실패하면 형식 인수 유추가 실패합니다.

인수 A 에 대한 인수 형식 Ta 과 매개 P변수의 매개 변수 형식 Tp 이 지정된 경우 형식 힌트는 다음과 같이 생성됩니다.

  • 메서드 형식 매개 변수가 포함되지 않으면 Tp 힌트가 생성되지 않습니다.

  • Ta 동일한 순위의 배열 형식인 경우 Tp 요소 형식 TaTp 으로 바꾸고 TaTp 배열 요소 제한으로 이 프로세스를 다시 시작합니다.

  • 메서드 형식 매개 변수 Ta 인 경우 Tp 현재 제한이 있는 형식 힌트로 추가됩니다(있는 경우).

  • 람다 메서드이고 생성된 대리자 형식이거나 TSystem.Linq.Expressions.Expression(Of T)생성된 대리자 형식인 경우 A 각 람다 메서드 매개 변수 형식 및 해당 대리자 매개 변수 형식 TLTD에 대해 프로세스를 제한 없이 바꾸고 TaTLTDTp 다시 시작합니다.Tp 그런 다음, 람다 메서드의 반환 형식으로 바꾸고 Ta 다음을 수행합니다.

    • 일반 람다 메서드이면 A 대리자 형식의 반환 형식으로 대체 Tp 합니다.
    • 비동기 람다 메서드이고 대리자 형식의 반환 형식에 일부 형식이 있으면 A 해당 T형식 Task(Of T) 으로 바꿉 Tp 다.T
    • 반복기 람다 메서드이고 대리자 형식의 반환 형식에 폼이 있거나 IEnumerable(Of T) 일부 형식이 있으면 A 해당 T메서드 IEnumerator(Of T) 로 바꿉 TpT다.
    • 다음으로, 제한 없이 프로세스를 다시 시작합니다.
  • 메서드 포인터이고 Tp 생성된 대리자 형식인 경우 A 매개 변수 형식 Tp 을 사용하여 가리키는 메서드가 가장 적합한지 확인합니다Tp. 가장 적용 가능한 메서드가 있는 경우 메서드의 반환 형식과 Tp 대리자 형식의 반환 형식으로 바꾸고 Ta 제한 없이 프로세스를 다시 시작합니다.

  • 그렇지 않으면 Tp 생성된 형식이어야 합니다. 지정된 TG경우 , 제네릭 형식 ,Tp

    • 이 경우 형식을 TG정확히 한 번 상속하거나 구현 TG 한 다음 일치하는 각 형식 인수의 TaTpTpx 형식을 제네릭 인수 Tax 제한으로 TaxTpxTp 바꾸고 Ta 다시 시작합니다.TaTG

    • 그렇지 않으면 제네릭 메서드에 대한 형식 유추가 실패합니다.

형식 유추의 성공은 그 자체로 메서드가 적용 가능함을 보장하지 않습니다.