0

Consider the following class:

public class TwoWayMap<T1, T2>
{
    public T2 Get(T1 x)
    {
        throw new System.NotImplementedException();
    }

    public T1 Get(T2 x)
    {
        throw new System.NotImplementedException();
    }
}

If T1 and T2 are different types and we call Get, then the compiler knows which one we mean.

var map1 = new TwoWayMap<int, string>();
map1.Get("hello");
map1.Get(5);

However, if the types are equal, then the two methods share the same signature. And in terms of overload resolution, they are equally specific (compared to, say, a generic vs a non-generic parameter). Therefore, we cannot call the method unambiguously.

var map2 = new TwoWayMap<int, int>();
map2.Get(5);

Compiler Error CS0121: The call is ambiguous between the following methods or properties: 'TwoWayMap.Get(T1)' and 'TwoWayMap.Get(T2)'

Of course, we can (and should) avoid this issue by not using equal types or by providing dedicated Get1 and Get2 methods, but I am wondering: Is there some way in C# or .NET to disambiguate this? Is it possible to call map2.Get()?

Community
  • 1
  • 1
Sebastian Negraszus
  • 11,915
  • 7
  • 43
  • 70
  • Only through reflection, but then the choice is arbitrary - there's no way to distinguish one method over the other. – D Stanley Sep 02 '15 at 16:59
  • I suggest just using different names for the `Get`s. It would be much clearer as to what the code is actually doing when someone quickly glances at it. – TyCobb Sep 02 '15 at 17:02
  • But the compiler already guarantees this can't happen, so why ask if there's another way the compiler can guarantee it won't happen? –  Sep 02 '15 at 17:17

2 Answers2

1

If I updated that API to use GetSource and GetTarget I would have no idea which one Get(5) would be, How is the compiler supposed to know?

Although looking a little closer at the question I think you could use GetMethods() and just invoke the second one returned.

James
  • 9,774
  • 5
  • 34
  • 58
0

you can do something like this

interface IGetter1<T1,T2>
{
    T2 Get(T1 x);
}

interface IGetter2<T1, T2>
{
    T2 Get(T1 x);
}
public class TwoWayMap<T1, T2> : IGetter1<T1,T2>,IGetter2<T2,T1>
{
    public T2 Get(T1 x)
    {
        throw new System.NotImplementedException();
    }

    public T1 Get(T2 x)
    {
        throw new System.NotImplementedException();
    }
}

var map1 = new TwoWayMap<int, int>();
        var map2 =(IGetter1<int,int>) map1;
        var map3 = (IGetter2<int, int>) map1;
     //   map2.Get(5);
        map3.Get(5);
Viru
  • 2,228
  • 2
  • 17
  • 28
  • @Servy Yes it is much cleaner and better than using reflection and reflection has some performance implication... – Viru Sep 02 '15 at 17:26
  • I didn't say anything about using reflection. – Servy Sep 02 '15 at 17:29
  • @servy reflection was suggested by someone as one of the approach...I was just pointing out that....I don't have enough reps yet to comment on that thread directly. :) – Viru Sep 02 '15 at 17:41
  • Both of them are very poor solutions, and neither of them should be used. Why you've decided to tell me that your solution is a tad better than another person's very poor solution, while still much, much worse than the solution *I* mentioned is beyond me. – Servy Sep 02 '15 at 17:59