2009-10-22 8 views
4

Pour le contexte - read this.Question délicate sur les génériques, l'héritage et le chaînage

Problème:

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

Ceci est une technique comment la méthode 'mimétique' de classe de base qui est en mesure de retourner type dérivé collationnée (sinon mon b ne pouvait pas appelez encore le buzz().

aller plus loin et faire foo/bar générique (cela fonctionne toujours très bien):

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

Et la question est -
comment passer lambda à la méthode fizz qui connaît tbuzz et c'est propriétés sans passer paramètre/s explicitement.

code cassé qui pourrait refléter ce que je cherche:

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

Vous vous demandez si cela est possible. Et si non - pourquoi? Théoriquement - foo<T> sait qu'il y a un buzz en dessous.

Existe-t-il une autre approche pour créer une méthode de base ou imiter celle-ci qui supporte le chaînage pour de telles classes?

+1

On dirait que le problème est d'inférer le type 'Tbuzz' pour' fizz ', qui n'est pas connecté du tout avec' foo '. Par curiosité, j'ai essayé de changer la contrainte sur T en 'où T: Foo ' en vain. – outis

+0

Comme je l'ai écrit - ces lignes sont brisées. J'ai compris que fizz n'est pas connecté aussi. La question est - peuvent-ils être connectés et sinon - pourquoi? –

Répondre

1

Je ne pense pas que ce que vous essayez d'accomplir est possible. En théorie, ce que vous auriez besoin est une sorte de contrainte comme:

where TBuzz : T<inner> 

signifie TBuzz doit être le type qui est le type générique interne de T. Ce n'est pas possible pour autant que je sache.

0

cela?

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

Non. Pas vraiment. Foo est censé être générique. Il devrait avoir un paramètre de type dérivé de buzz. Et lambda devrait reconnaître le buzz. –

0

Au début, je pensais que je fait des progrès avec une sorte de Thrush combinator

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

mais qui semble être une impasse. Posté de toute façon au cas où vous pourriez l'améliorer.