2010-04-13 3 views
47

J'ai lu dans un livre électronique quelque part (que je suis désespéré de retrouver), qui, à l'aide des délégués, il est possible d'écrire du code qui a la syntaxe comme suit:Est-il possible d'écrire une syntaxe comme -()()?

()(); // where delegate precedes this. 

Quelqu'un peut-il fournir des détails comment cela serait possible/dans quelle situation cela se produirait?

+10

Quel est le but possible pour cela (autre que d'avoir deux yeux vides vous regardent dans le code)? –

+1

Cette question fait vraiment ressortir le côté obscur de la Force - je suis impressionné de voir des esprits si brillants rivaliser avec enthousiasme pour produire un code véritablement horrifiant! – Mathias

+2

@Mathias: Code mal est le funnest. Et la «meilleure» partie est, plus votre code devient diabolique, plus vous le voulez. –

Répondre

127

Vous pouvez faire un peu mieux que les exemples donnés à ce jour, en fait ... vous pouvez l'étendre de façon arbitraire:

class Test 
{ 
    delegate Hofstadter Hofstadter(); 

    static void Main() 
    { 
     // Unfortunately I'm clearly not as smart as the real thing 
     Hofstadter douglas =() => null; 

     douglas()()()()()()(); 
    } 
} 

Et voici une autre alternative horrible, pour l'art supplémentaire ASCII:

class Test 
{ 
    delegate __ ___(); 
    delegate ___ __(___ _); 

    static void Main() 
    { 
     ___ _ =() => null; 

     _()((_))(); 
    } 
} 

S'il vous plaît ne jamais, jamais le faire.

EDIT: Un dernier - bien qu'il soit autant de simplement remplacer les choses par des underscores comme toute autre chose, et la réutilisation des noms chaque fois que possible:

class Test 
{ 
    delegate void _(); 
    delegate __<_> ___<_>(); 
    delegate ___<_> __<_>(___<_> ____); 

    static ___<_> ____<_>(___<_> ____) { return ____; } 
    static __<_> ____<_>() { return ____<_>; } 

    static void Main() 
    { 
     ((__<_>)____)(____<_>)(); 
    } 
} 
+181

Je suis à peu près sûr que cela convoque un vélociraptor. – womp

+2

Une astuce similaire à la première (un délégué qui accepte un lui-même en tant que paramètre) peut être "utile": le combinateur Y! (http://blogs.msdn.com/madst/archive/2007/05/11/recursive-lambda-expressions.aspx ATTENTION: pas pour les faibles d'esprit!) –

+20

C'est en fait une incantation secrète qui confère des capacités de super-héros C# à la personne qui le dit. Malheureusement, cela ne fonctionne qu'une seule fois et Jon l'utilise déjà. –

9
static void Foo() 
{ 
    Console.WriteLine("Hello World!"); 
} 

static Action Bar() 
{ 
    return new Action(Foo); 
} 

static void Main() 
{ 
    Func<Action> func = new Func<Action>(Bar); 
    func()(); 

    Bar()(); 
} 

impressions

 
Hello World! 
Hello World! 

Cela fonctionne, parce que func() et Bar() retourner un délégué Action qui peut être invoqué en utilisant la syntaxe normale d'appel de méthode.

+0

Je pense que c'est le cas le plus courant; code qui doit rechercher un délégué différent en fonction des circonstances. J'ai un code qui fait 'ConstructFunc (key) (obj)'. – porges

35

Voici un exemple de programme qui démontre ceci:

using System; 

class Program 
{ 
    static Action GetMethod() 
    { 
     return() => Console.WriteLine("Executing"); 
    } 
    static void Main() 
    { 
     GetMethod()(); 
     Console.ReadKey(); 
    } 
} 

Cela étant dit, je ne jamais faire dans le code de production. C'est très inattendu.


Edit: Juste au cas où vous voulez voir quelque chose encore plus laid ... [en particulier le "()()[()=>{}]()"]:

using System; 

class Program 
{ 
    static void Main() 
    { 
     (new Program()).Confusion(); 
     Console.ReadKey(); 
    } 

    public Action this[Action index] 
    { 
     get { 
      return() => Console.WriteLine("Executing"); 
     } 
    } 

    Func<Program> GetInstance() 
    { 
     return() => this; 
    } 

    void Confusion() 
    { 
     // This is particularly ugly... 
     GetInstance()()[()=>{}](); 
    } 
} 
+6

Mec. C'est juste ... Je ne sais pas. Je vais chercher des endroits pour le faire dans une application de production maintenant, bien que ce soit un acte de grand mal. –

+3

+ 1 pour aller encore plus loin dans la réalisation de cet extra-horrible – Mathias

2

Quelque chose comme:

delegate void FunctionA(); 
delegate FunctionA FunctionB(); 

void TestA() { } 
FunctionA TestB() { return TestA; } 

void Main() 
{ 
    TestB()(); 
} 
0

Si vous avez une fonction qui renvoie un délégué que vous associeriez généralement à un signal, mais que vous souhaitez appeler cette fonction immédiatement, vous pouvez utiliser cette syntaxe.

12

Vous avez juste besoin d'un référencement peu de soi-même, et vous pouvez l'appeler autant de fois que vous le souhaitez:

delegate Foo Foo(); 

class Program { 
    static void Main(string[] args) { 
     Foo f = null; 
     f =() => f; 
     // Add more "()" as you feel like... 
     f()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()(); 
    } 
} 
+0

+1: très soigné et intelligent –

+0

Ici, 'f' est une fonction" identité "d'un autre ordre, renvoyant elle-même (plutôt que son paramètre) –

+0

+1 pour être arbitrairement extensible! –

Questions connexes