Generic overloading badness

Hi

I wrote a class that looked something like this:

class Factory
{
void UpdateCache<T>(T object) { }
void UpdateCache(IObjectList list) { }
}

I then used the methods on a variety of objects, including classes implementing IObjectList. This compiled without any warnings. However, the second version of the method (taking IObjectList) is only called if its parameter is explicitly cast to IObjectList.

It's debatable whether this is the correct behaviour or not, but at the very least, shouldn't this raise a warning IMHO the least generic (or most specialized) method callable is the one that should be called. I can't immediately see a reason why this is difficult or impossible.



Answer this question

Generic overloading badness

  • Marius Onofrei

    I am amazed that compiled without warnings, let alone errors - but I can understand why you would have to cast to IObjectList in order to use the second version.

    What I dont understand is why you have the two methods - if they both do the same thing then get rid of the second one, if they do different things then check the type within the first one and use a case statement - but if this confuses you and you wrote it think what its going to do to other people:)

    Ross



  • wbbeasley

    Hello All.

    David:

    I apologize, I mis-understood the point of the question.  Please disregard.



  • rtaiss

    And lo, the angel of C# spake from the holy book (The C# Language Reference, second edition) saying turn to section 20.9 (p. 525).

    Ok, that was just too silly. But, I did see Spamalot the Musical last week.

    But, S 20.5 (Revised Lookup Rules) does have the answer (p. 525)

    "Next, interface members that are hidden by class members are removed from the set. ... If M is a method, then ... all methods with the same signature as M declared in an interface declaration are removed from the set".

    That means any interface methods lose to generic equivalents. All candidate methods declared in an interface are hidden behind applicable generic methods when doing a method lookup.



  • M. Nicholas

    The problem is that UpdateCache<T>(T object) is going to be an exact match to every object, so the only to get the other method to match anything is to pass it a IObjectList (which is why you have to cast it to specifically that interface).

    So, we must make either the first a worse match, or the second a better match.

    We can make the first a worse match, by adding a where clause:

    void UpdateCache<T>(T object) where T: ______

    You'll have to come up with something appropriate for _____ yourself, but confident that there is something we can use (a common base class or interface)

    Alternately, we can make the second method a better match by doing something like:

    void UpdateCache<T>(IObjectList<T> list) { }

    This would require code changes to all the classes which implement IObjectList.



  • KnobCreek

    hi

    did you implement the IObjectList interface explicitly

    this would mean that you need to cast your object to IObjectList before you can access any of the IObjectList methods..

    Hence the need for casting before you call the method.

    You could just implement it implicitly, or do as above, delete the second method and use a case statement

    Hope this helps, please close the thread if it does



  • ClaudiaHelpOnVSTO

    Hello David,

    Here you use generics in the way:

    class Factory
    {
        void UpdateCache<T>(T object) { }
        void UpdateCache(IObjectList list) { }
    }

    And when you use the Factory.UpdateCache(list) , assuming list has implemented IObjectlist interface, actually it seems right to call either method, it's amphibolous! Since "list" is also match the generics one. So, the code does not demonstrate clearly enough for us which one you really mean to call, how we human know Let alone machines.

    So, try to improve your idea and design, at least make the syntax with definite meaning.

    Thank you



  • Generic overloading badness