Re: Type inference in extension methods...

Mark Nicholls <[email protected]>
Newsgroups gmane.comp.windows.devel.dotnet.advanced
Message-ID <LISTSERV%[email protected]>
I've simplified it as much as I can! and created and example....Boom9 does work...Boom10 wont infer...even though there is a solution (explicitly stated)...and there's not another obvious one

The difference between the two methods is that Boom10 has a type parameter BarB which is constrained by the explicit constrait
"BarB : ABar<BarB, DNT>"
and should be derivable from the constraint on CompundBarBC
"CompundBarBC : ACompoundBar<CompundBarBC, BarB, DNBar, CompoundFooBC, DNT, DNT>"

in Boom9 BarB doesn't appear and CompundBarBC is explicitly constrained
"CompoundBarBC : ACompoundBar<CompoundBarBC, DNBar, DNBar, CompoundFooBC, DNT, DNT>"

so it would seem in Bar9 the inference works uniquely (assuming that inference implies uniquenes, which I think it does)...and that CompoundBC is derived (in the failed inference on Boom10) to be 
"CompoundBar<DNBar, DNBar, CompoundFoo<DNT, DNT>, DNT, DNT>"

naively I would assume that in Boom10 it can derive the same fact as Boom9...yet it does not derive that BarB is DNBar....which I think it has to be....i.e.   A : B<C> and A : B<D> means that C == D (as dot net does not support co/contravariance)

P.S. I deliberately use abstract classes rather than interfaces as abstract classes are more constrained (i.e. single inheritance) making the inference as strong as possible.

heres the simplified code!


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

class Test
{
    public static void X()
    {

        CompoundBar2<DNBar, DNT> y = new CompoundBar2<DNBar, DNT>();

        new DNBar().Boom9(y);       // inference works
        new DNBar().Boom10(y);     // inference doesn't work
        new DNBar().Boom10<        // there is a solution
            CompoundBar2<DNBar, DNT>,
            CompoundBar<DNBar, DNBar, CompoundFoo<DNT, DNT>, DNT, DNT>,
            CompoundFoo<DNT, CompoundFoo<DNT, DNT>>,
            CompoundFoo<DNT, DNT>,
            DNBar>(y);
    }
}

abstract class AFoo<This>
    where This : AFoo<This>, new()
{
}

abstract class AFoo2<This> : AFoo<This>
    where This : AFoo2<This>, new()
{
}

abstract class ACompoundFoo<This, A, B> : AFoo<This>
    where This : ACompoundFoo<This, A, B>, new()
    where A : AFoo<A>, new()
    where B : AFoo<B>, new()
{
}

class CompoundFoo<A, B> : ACompoundFoo<CompoundFoo<A, B>, A, B>
    where A : AFoo<A>, new()
    where B : AFoo<B>, new()
{
}

sealed class Foo : AFoo2<Foo>
{
}

sealed class DNT : AFoo2<DNT>
{
}
abstract class ABar<This, A> 
    where This : ABar<This, A>
    where A : AFoo<A>, new()
{
    public void
    Boom10<CompoundBarABC, CompundBarBC, CompoundFooABC, CompoundFooBC, BarB>(
        ACompoundBar<CompoundBarABC, This, CompundBarBC, CompoundFooABC, A, CompoundFooBC> abc)
        where CompoundBarABC : ACompoundBar<CompoundBarABC, This, CompundBarBC, CompoundFooABC, A, CompoundFooBC>
        where CompundBarBC : ACompoundBar<CompundBarBC, BarB, DNBar, CompoundFooBC, DNT, DNT>
        where BarB : ABar<BarB, DNT>
        where CompoundFooABC : ACompoundFoo<CompoundFooABC, A, CompoundFooBC>, new()
        where CompoundFooBC : ACompoundFoo<CompoundFooBC, DNT, DNT>, new()
    {
    }

    public void
    Boom9<CompoundBarABC, CompoundBarBC, CompoundFooABC, CompoundFooBC>(
        ACompoundBar<CompoundBarABC, This, CompoundBarBC, CompoundFooABC, A, CompoundFooBC> abc)
        where CompoundBarABC : ACompoundBar<CompoundBarABC, This, CompoundBarBC, CompoundFooABC, A, CompoundFooBC>
        where CompoundBarBC : ACompoundBar<CompoundBarBC, DNBar, DNBar, CompoundFooBC, DNT, DNT>
        where CompoundFooABC : ACompoundFoo<CompoundFooABC, A, CompoundFooBC>, new()
        where CompoundFooBC : ACompoundFoo<CompoundFooBC, DNT, DNT>, new()
    {
    }


}

abstract class ACompoundBar<This, ThisA, ThisB, AB, A, B> : ABar<This, AB>
    where This : ACompoundBar<This, ThisA, ThisB, AB, A, B>
    where ThisA : ABar<ThisA, A>
    where ThisB : ABar<ThisB, B>
    where AB : ACompoundFoo<AB, A, B>, new()
    where A : AFoo<A>, new()
    where B : AFoo<B>, new()
{
}

class CompoundBar<ThisA, ThisB, AB, A, B> : ACompoundBar<CompoundBar<ThisA, ThisB, AB, A, B>, ThisA, ThisB, AB, A, B>
    where ThisA : ABar<ThisA, A>
    where ThisB : ABar<ThisB, B>
    where AB : ACompoundFoo<AB, A, B>, new()
    where A : AFoo<A>, new()
    where B : AFoo<B>, new()
{

}

class DNBar : ABar<DNBar, DNT>
{
}

class CompoundBar2<BarA, T> :
    ACompoundBar<
        CompoundBar2<BarA, T>,
        BarA,
        CompoundBar<BarA, BarA, CompoundFoo<T, T>, T, T>,
        CompoundFoo<T, CompoundFoo<T, T>>,
        T,
        CompoundFoo<T, T>>
    where BarA : ABar<BarA, T>
    where T : AFoo<T>, new()
{
}





 

===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.