4

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?

Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195
  • 1
    Looks like the issue is with inferring type `Tbuzz` for `fizz`, which isn't connected at all with `foo`. Out of curiosity, I tried changing the constraint on T to `where T : Foo` to no avail. – outis Oct 22 '09 at 01:29
  • As i wrote - those lines are broken. I understood that fizz is not connected too. Question is - can they be connected and if not - why? – Arnis Lapsa Oct 22 '09 at 06:57

3 Answers3

1

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
  • 102,548
  • 21
  • 159
  • 201
0

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
  • 4,267
  • 33
  • 40
  • No. Not really. Foo is supposed to be generic. It should have type parameter that derives from buzz. And lambda should recognize buzz. – Arnis Lapsa Oct 22 '09 at 06:54
0

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
  • 30,834
  • 6
  • 70
  • 106