Сложный вопрос о дженериках, наследовании и сцеплении - PullRequest
4 голосов
/ 22 октября 2009

Для контекста - прочитайте это .

Проблема:

 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;
        }
    }

Решение:

 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;
        }
    }

Это методика «имитации» метода базового класса, который может возвращать обратно производный тип (в противном случае мой b не мог бы снова вызвать buzz ()).

Пойдем дальше и сделаем foo / bar родовым (это все равно будет работать нормально):

  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;
        }
    }

И вопрос -
как передать лямбду в fizz метод, который знает о tbuzz и его свойствах без явной передачи параметра типа / s .

Неработающий код, который может отражать то, что я ищу:

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;
        }
    }

Интересно, если это возможно. А если нет - почему?

Теоретически - foo<T> знает, что внизу есть buzz.

Есть ли другой подход, как создать базовый метод или имитировать его, который поддерживает цепочку для таких классов?

Ответы [ 3 ]

1 голос
/ 22 октября 2009

Я не думаю, что вы пытаетесь достичь возможно. Теоретически, вам нужно что-то вроде ограничения:

where TBuzz : T<inner> 

означает, что TBuzz должен быть типом, который является внутренним универсальным типом T. Насколько я знаю, это невозможно.

0 голосов
/ 22 октября 2009

Сначала я думал, что добился прогресса с неким Комбинацией дроздов

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

но это кажется тупиком. В любом случае, если вы сможете улучшить его, отправьте.

0 голосов
/ 22 октября 2009

это

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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...