Domanda

Lo so che può essere fatto in Java, come ho usato questa tecnica abbastanza ampiamente in passato. Un esempio in Java sarebbe mostrato di seguito. (Ulteriori domanda. Che cosa è questa tecnica chiamata? E 'difficile trovare un esempio di questo senza un nome.)

public abstract class Example {
   public abstract void doStuff();
}

public class StartHere{
   public static void main(string[] args){
      Example x = new Example(){
         public void doStuff(){
            System.out.println("Did stuff");
         }            
      };
      x.doStuff();
   }
}

Ora, la mia domanda principale sarebbe, questo può anche essere fatto in C #, e se sì, come?

È stato utile?

Soluzione

Con le espressioni Lamba e inizializzatori classe si può ottenere lo stesso comportamento con un po 'di sforzo.

public class Example {
    public Action DoStuff;
    public Action<int> DoStuffWithParameter;
    public Func<int> DoStuffWithReturnValue;
}

class Program {
    static void Main(string[] args) {
        var x = new Example() {
            DoStuff = () => {
                Console.WriteLine("Did Stuff");
            },
            DoStuffWithParameter = (p) => {
                Console.WriteLine("Did Stuff with parameter " + p);
            },
            DoStuffWithReturnValue = () => { return 99; }


        };

        x.DoStuff();
        x.DoStuffWithParameter(10);
        int value = x.DoStuffWithReturnValue();
        Console.WriteLine("Return value " + value);
        Console.ReadLine();
    }
}

Un problema con questa soluzione che ho capito è che se si dovesse creare campi nella classe di esempio, le espressioni lambda non sarebbe in grado di accedere a tali campi.

Tuttavia, non v'è alcuna ragione per cui non si poteva passare l'istanza di esempio per le espressioni lambda che darebbe loro l'accesso a qualsiasi stato di pubblico che ad esempio potrebbe contenere. Per quanto ne so che sarebbe funzionalmente equivalente al Java Anonymous classe interna.

P.S. Se avete intenzione di votare una risposta verso il basso, fare a tutti noi un favore e aggiungere un commento sul motivo per cui non siete d'accordo: -)

Altri suggerimenti

La tecnica di Java è chiamata "classe interna anonimo ", e non esiste un equivalente in C #.

In genere, i problemi che vengono risolti con le classi interne anonime in Java sono risolti in un modo molto più pulito utilizzando i delegati in .Net. Il vostro esempio è un po 'troppo semplicistico per determinare il vostro intento. Se il vostro intento utilizzando la classe astratta è quello di passare intorno ad un "comportamento" pensare solo utilizzando un delegato Action invece.

public class StartHere{
   public static void main(string[] args){
      Action doStuff = () => Console.WriteLine("Did stuff");
      executeSomething(doStuff);
   }

   public static void executeSomething(Action action)
   {
      action();
   }
}

Questo non può essere fatto in C #; è necessario dichiarare un nuovo tipo di classe. Il più vicino si può ottenere in C # è probabilmente una classe annidata denominata:

public class StartHere{
    private class Foo : Example {
        public override void  doStuff()
        {
            Console.WriteLine("did stuff");
        }
    }
   public static void Main(string[] args){
      Example x = new Foo();
      x.doStuff();
   }
}

Questa non è supportata in C #, e se fosse per me non dovrebbe essere così sia.

La proliferazione di classi interne in java è principalmente dovuta alla mancanza di delegati o lambda, che C # ha. Così, mentre questo tipo di funzionalità attualmente è "la vostra unica speranza" in Java, di solito si può utilizzare altri meccanismi in C # per raggiungere gli stessi fini. Java si sente come suonare il pianoforte con una mano in questo senso.

(È vero che molti di noi hanno ottenuto abbastanza bravo a questo gioco con una sola mano, e ora sembra che dovremo aspettare almeno fino a Java 8 per le chiusure ...)

Dal momento che la classe rappresenta solo un'azione, è possibile utilizzare un delegato nel tuo caso, non v'è un delegato esistente:

public delegate void Action();

Questa è l'esatto equivalente della classe.

e la dichiarazione della classe anonima è ancora più pulito:

Action action = () => Console.WriteLine("Hello world");
action(); // invoke

si può anche utilizzare la chiusura:

public void Hello(string name)
{
  Action action = () => Console.WriteLine("Hello " + name);
  action(); // will call the above lambda !
}

Mentre tutte le buone risposte, la maggior parte dei arounds di lavoro proposti si basano su C # 3.0

Quindi, per ragioni di completezza, aggiungerò un'altra soluzione che utilizza né lambda né di tipo Func (ammesso che, come Matt Olenik accennato nei commenti, si potrebbe generalizzare i delegati di seguito per funzionare allo stesso modo.). Per chi, come me che può essere ancora lavorando con C # 2.0. Forse non è la soluzione migliore, ma funziona.

public class Example
{
    public delegate void DoStuffDelecate();
    public DoStuffDelecate DoStuff;
    public delegate void DoStuffWithDelecate(int n);
    public DoStuffWithDelecate DoStuffWithParameter;
    public delegate int DoStuffWithReturnDelecate();
    public DoStuffWithReturnDelecate DoStuffWithReturnValue;
}

class Program
{
    static int MethodWithReturnValue()
    {
        return 99;
    }
    static void MethodForDelecate()
    {
        Console.WriteLine("Did Stuff");
    }
    static void MethodForDelecate(int n)
    {
        Console.WriteLine("Did Stuff with parameter " + n);
    }


    static void Main(string[] args)
    {
        var x = new Example();
        x.DoStuff = MethodForDelecate;
        x.DoStuffWithParameter = MethodForDelecate;
        x.DoStuffWithReturnValue = MethodWithReturnValue;

        x.DoStuff();
        x.DoStuffWithParameter(10);
        int value = x.DoStuffWithReturnValue();
        Console.WriteLine("Return value " + value);
        Console.ReadLine();
    }
}

Siete in grado di raggiungere questo obiettivo con derisione in .NET. Tuttavia non v'è alcun supporto in-lingua per questa funzione, penso che sarà disponibile in C # 4.0. Ci sono una serie di librerie là fuori per Mocking, tra cui:

In breve no, è necessario definire come classe sub separata. Penso che questa funzione è venuta C # 4.0 però?

Modifica No non è venuta C # 4.0 Ho fatto che fino.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top