2009-04-03 4 views
0

두 유형 매개 변수 인 Generic<A, B>을 사용하는 제네릭 클래스가 있습니다. 이 클래스에는 매우 긴 별개의 서명이있는 메소드가 있으며 AB은 별개입니다. 그러나 A == B 인 경우 서명이 정확히 일치하고 과부하 해결을 수행 할 수 없습니다. 어떻게 든이 사건의 전문화 방법을 지정할 수 있습니까? 또는 컴파일러가 임의로 일치하는 오버로드 중 하나를 선택하도록 강제 하시겠습니까? 당신이 독단적으로 일을 결정하는 컴파일러를 원하는 경우에, 당신이 메서드를 호출의 목적은 무엇사례 A == B에 대해 GenericType <A,B>의 구현을 특수화 하시겠습니까?

using System; 

namespace Test 
{ 
    class Generic<A, B> 
    { 
     public string Method(A a, B b) 
     { 
      return a.ToString() + b.ToString(); 
     } 

     public string Method(B b, A a) 
     { 
      return b.ToString() + a.ToString(); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Generic<int, double> t1 = new Generic<int, double>(); 
      Console.WriteLine(t1.Method(1.23, 1)); 

      Generic<int, int> t2 = new Generic<int, int>(); 
// Following line gives: 
//  The call is ambiguous between the following methods 
//  or properties: 'Test.Generic<A,B>.Method(A, B)' and 
//  'Test.Generic<A,B>.Method(B, A)' 
      Console.WriteLine(t2.Method(1, 2)); 
     } 
    } 
} 

답변

2

덕분에, 그들은이 솔루션으로 나를 메시지 : 일치하는 오버로드

using System; 

namespace Test 
{ 
    class Generic<A, B> 
    { 
     public string Method(A a, B b) 
     { 
      return this.DefaultMethod(a, b); 
     } 

     protected string DefaultMethod(A a, B b) 
     { 
      return a.ToString() + b.ToString(); 
     } 

     public string Method(B b, A a) 
     { 
      return b.ToString() + a.ToString(); 
     } 
    } 

    class Generic<A> : Generic<A, A> 
    { 
     public new string Method(A a, A b) 
     { 
      return base.DefaultMethod(a, b); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Generic<int, double> t1 = new Generic<int, double>(); 
      Console.WriteLine(t1.Method(1.23, 1)); 

      Generic<int> t2 = new Generic<int>(); 
      Console.WriteLine(t2.Method(1, 2)); 
     } 
    } 
} 
+0

좋은 해결책. 그냥 두 가지 일반적인 클래스를 만드는 생각하지 않았다 :) – Damovisa

-1

번호

입니까?

+0

하나가 아닌 어떤 임의의 방법. 일치하는 오버로드가 모두 동등한 동작을 가져야하거나 클래스가 어쨌든 손상 될 수 있습니다. – Dave

3

컴파일러에 과부하를 강요하는 방법이 없습니다. 두 가지 방법 중 승자를 구별 할 수있는 방법이 없습니다.

하나만 선택하는 것이 좋지만 의사 결정이 결정적이어야합니다. 파일의 첫 번째 파일만큼 단순한 것조차도 부분 클래스를 고려해야하기 때문에 실제로 수행 할 수 없습니다. 각각 다른 파일에 있다면 컴파일러는 첫 번째 방법을 어떻게 선택합니까?

당신이 할 수있는 일은 int를 받아 들일 수있는 비 제네릭 버전의 메소드를 추가하는 것입니다. 컴파일러는 제네릭 버전보다 비 제네릭 버전을 선택할 것이고이 매우 제한된 시나리오에서 승리를 이끌 것입니다. 당신은 충돌이 있을지도 모른 각 유형을 위해 저것을 반복해야 할 것입니다.

예를 들면. 이 메서드를 추가하면 컴파일 오류가 해결되지만 int에 대해서만 해결됩니다.

public string Method(int b, int a) 
{ 
    return b.ToString() + a.ToString(); 
} 
1

나는 그것이 종류의 일반의 목적을 패배 알고 있지만, 어떤 종류의 object의 두 개의 매개 변수를 복용 한 번 방법을 정의하는 방법에 대한?

메서드 내에서 유형을 검사하고 두 가지 옵션 중 어느 것을 호출 할 것인지 결정할 수 있습니다.

namespace Test 
{ 
    class Generic<A, B> 
    { 
     public string Method(object a, object b) 
     { 
      if (a is A && b is B) 
       return MethodOneTwo; 
      else if (a is B && b is A) 
       return MethodTwoOne; 
      else 
       throw new ArgumentException("Invalid Types"); 
     } 

     private string MethodOneTwo(A a, B b) 
     { 
      return a.ToString() + b.ToString(); 
     } 

     private string MethodTwoOne(B b, A a) 
     { 
      return b.ToString() + a.ToString(); 
     } 
    } 
} 
0

리플렉션을 사용하여 메소드를 가져 와서 임의로 호출합니다. 메서드를 가져올 때마다 예상되는 매개 변수와 반환 형식을 필터링하면 더 강력 해집니다.

using System; 
using System.Collections.Generic; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    using System; 
    using System.Reflection; 

    namespace Test 
    { 
     class Generic<A, B> 
     { 
      public string Method(A a, B b) 
      { 
       return a.ToString() + b.ToString(); 
      } 

      public string Method(B b, A a) 
      { 
       return b.ToString() + a.ToString(); 
      } 
     } 

     class Program 
     { 
      static void Main(string[] args) 
      { 
       Generic<int, double> t1 = new Generic<int, double>(); 
       Console.WriteLine(t1.Method(1.23, 1)); 

       Generic<int, int> t2 = new Generic<int, int>(); 
       // Following line gives: 
       //  The call is ambiguous between the following methods 
       //  or properties: 'Test.Generic<A,B>.Method(A, B)' and 
       //  'Test.Generic<A,B>.Method(B, A)' 
       MethodInfo [] methods = t2.GetType().GetMethods(); 
       foreach(MethodInfo method in methods) 
       { 
        if (method.Name == "Method") 
        { 
         method.Invoke(t2,new Object[2] {1,2}); 
         break; 
        } 
       } 
      } 
     } 
    } 
} 

편집 : 자레드의 솔루션과 비슷한 문제에 대한 블로그입니다. 우리가 정말 필요한 것은

http://shiman.wordpress.com/2008/07/07/generic-method-overload-a-trap-for-c-net-library-developers/

사전 컴파일에서 콘크리트 서명을 생성하거나 컴파일 시간 템플릿입니다. 좋은 답변을