views:

205

answers:

3

For context - read this.

Problem:

 class Program
    {
        static void Main()
        {
            var b = new bar();

            b.buzz().fizz().buzz().fizz(); //cool
            //              ^FAIL!!!...<------------------------------------
            Console.ReadLine();
        }
    }

    public class foo
    {
        public foo fizz() { return this; }
    }

    public class bar : foo
    {
        public bar buzz()
        {
            return this;
        }
    }

Solution:

 class Program
    {
        static void Main()
        {
            var b = new bar();

            b.buzz().fizz().buzz().fizz(); //cool stuff
            Console.ReadKey();
        }
    }

    public static class fooExtensions
    {
        public static T fizz<T>(this T t) where T : foo
        { return t; } 
    }

    public class foo{}

    public class bar : foo
    {
        public bar buzz()
        {
            return this;
        }
    }

This is a technique how to 'mimic' method of base class which is able to return back derived type (otherwise my b couldn't call buzz() again).

Going further and making foo/bar generic (this will still work fine):

  class Program
    {
        static void Main()
        {
            var b = new bar<buzz>();

            b.buzz().fizz().buzz().fizz(); //cool
            Console.ReadLine();
        }
    }

    public static class fooExtensions
    {
        public static T fizz<T>(this T t) where T : foo<buzz>
        { return t; }
    }

    public class buzz { public string name { get; set;} }

    public class foo<T> where T : buzz
    {}

    public class bar<T> : foo<T> where T : buzz
    {
        public bar<T> buzz()
        {
            return this;
        }
    }


And the question is -
how to pass lambda to fizz method that knows about tbuzz and it's properties without passing type parameter/s explicitly.

Broken code that might reflect what i'm looking for:

class Program
    {
        static void Main()
        {
            var b = new bar<buzz>();

            b.buzz().fizz(x=>x.name).buzz().fizz(); //not cool anymore
            //               ^FAIL!!!<---------------------------------
            Console.ReadLine();
        }
    }

    public static class fooExtensions
    {
        //NO IDEAS WHAT TO WRITE BELOW!!!
        public static T fizz<T, Tbuzz>(this T t, 
            Func<Tbuzz, object> superlambda)
            where T : foo<buzz>
            where Tbuzz : buzz 
        {
            return t;
        }
    }

    public class buzz { public string name { get; set;} }

    public class foo<T> where T : buzz
    {}

    public class bar<T> : foo<T> where T : buzz
    {
        public bar<T> buzz()
        {
            return this;
        }
    }

Wondering if that's possible. And if not - why?

Theoretically - foo<T> knows that there's a buzz underneath.

Are there any other approach how to create base method or mimic it that supports chaining for such a classes?

+1  A: 

I don't think what you're trying to accomplish is possible. Theoretically what you would need is some kind of constraint like:

where TBuzz : T<inner>

meaning TBuzz needs to be the type that's the inner generic type of T. This isn't possible as far as I know.

BFree
A: 

this?

class Program
{
    static void Main(string[] args)
    {
        var b = new bar();
        var a = b.buzz().fizz(x => x.name).buzz().fizz();
        Console.ReadLine();
    }
}

public static class fooExtensions
{
    public static T fizz<T>(this T t) where T : foo
    { return t; }

    public static T fizz<T>(this T t,
        Func<T, object> superlambda)
        where T : foo
    {
        return t;
    }
}

public class foo { public string name { get; set; } }

public class bar : foo
{
    public bar buzz()
    {
        return this;
    }
}
Avram
No. Not really. Foo is supposed to be generic. It should have type parameter that derives from buzz. And lambda should recognize buzz.
Arnis L.
A: 

At first I thought I made progress with a kind of Thrush combinator

public static T fizz<T>(this T t, Func<T, T> f)
{ return f(t); }

but that seems to be a dead end. Posting it anyway in case you can improve it.

Jonas Elfström