2010-04-13 11 views
47

leí en un libro electrónico en algún lugar (que estoy desesperado por encontrar de nuevo), que, mediante el uso de los delegados, es posible escribir código que tiene la sintaxis de la siguiente manera:¿Es posible escribir sintaxis como -()()?

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

¿Alguien puede dar detalles de cómo esto sería posible/¿en qué situación ocurriría esto?

+10

¿Qué posible propósito podría haber para esto (aparte de tener dos ojos vacíos mirándote fijamente en el código)? –

+1

Esta pregunta realmente saca a relucir el lado oscuro de la Fuerza: ¡estoy impresionado de ver a esas mentes brillantes compitiendo con entusiasmo para producir un código genuinamente horroroso! – Mathias

+2

@Mathias: El código del mal es el más divertido. Y la "mejor" parte es que cuanto más malvado se vuelve tu código, más malvado quieres que sea. –

Respuesta

127

Usted puede hacer un poco mejor que los ejemplos dados hasta ahora, de hecho ... se puede extender de manera arbitraria:

class Test 
{ 
    delegate Hofstadter Hofstadter(); 

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

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

Y aquí hay otra alternativa horrible, por el arte ASCII adicional:

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

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

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

Nunca haga esto.

EDIT: Un último - aunque es tanto sobre sólo la sustitución de las cosas con guiones como cualquier otra cosa, y la reutilización de los nombres siempre que sea posible:

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

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

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

Estoy bastante seguro de que esto convoca a un velociraptor. – womp

+2

Un truco similar al primero (un delegado que acepta a sí mismo como parámetro) puede ser "útil": ¡el combinador Y! (http://blogs.msdn.com/madst/archive/2007/05/11/recursive-lambda-expressions.aspx ADVERTENCIA: ¡no para los débiles de la mente!) –

+20

En realidad, es un encantamiento secreto que otorga habilidades de superhéroe C# para la persona que lo dice Desafortunadamente, solo funciona una vez y Jon ya lo usa. –

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

impresiones

 
Hello World! 
Hello World! 

Esto funciona, porque func() y Bar() devolver un delegado Action cual puede ser invocado utilizando la sintaxis normal de invocación de método.

+0

Creo que este es el caso más común; código que necesita buscar un delegado diferente según las circunstancias. Tengo un código que hace 'ConstructFunc (clave) (obj)'. – porges

35

He aquí un programa de ejemplo que muestra esto:

using System; 

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

Dicho esto, yo no volvería a hacer esto en el código de producción. Es muy inesperado.


Editar: Sólo en caso de que quiera ver algo aún más feo ... [especialmente el "()()[()=>{}]()"]:

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

Dude. Eso es solo ... No sé. Voy a buscar lugares para hacer esto en una aplicación de producción ahora, aunque sea un acto de gran maldad. –

+3

+1 por hacer un esfuerzo adicional para hacer este extra-horrendo – Mathias

2

Algo así como:

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

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

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

Si tiene una función que devuelve un delegado que normalmente adjuntaría a una señal, pero desea llamar a esa función de inmediato, puede usar esta sintaxis.

12

Sólo se necesita un poco de auto referencia, y se le puede llamar tantas veces como se quiera:

delegate Foo Foo(); 

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

+1: Muy limpio e inteligente. –

+0

Aquí 'f' es una función de" identidad "de un tipo diferente, que se devuelve (en lugar de su parámetro). –

+0

+1 por ser arbitrariamente extensible! –

Cuestiones relacionadas