| 

.NET C# Java Javascript Exception

5
Hi Community,

ich bin auf einer Website über Action<T> gestolpert. Kann mir jemand sagen was das ist?
Und zwar bei:

public Action<int> SendMiles;

tack
News:
12.08.2010
tack 294 1 8
tack 294 1 8
4 Antworten
11
Action<T, ...> und Func<T, ...> sind Funktionstypen, also ein "Daten"-typ für ausführbaren Code.

Ein Func<T1, T2, ..., Tn, R> ist der Typ für ein Stück Code, welches n Parameter hat und einen Wert vom Typ R zurück gibt. Da es nicht erlaubt ist, einen generischen Typ-Parameter mit void zu instanziieren, muss es irgend eine andere Möglichkeit geben, einen Typ für eine Funktion, die keinen Wert zurück gibt, anzugeben, und das ist Action<T1, T2, ..., Tn>. Das ist im Prinzip dasselbe wie Func nur halt mit void als Rückgabetyp.

Wofür braucht man nun diese Funktionstypen? Immer dann, wenn man einer Methode ein Stück ausführbaren Code als Argument übergeben will!

Nimm zum Beispiel einmal an, foreach wäre nicht in die Sprache eingebaut, sondern eine ganz normale Methode. Was wäre ihre Signatur? Zunächst einmal "macht" foreach nur etwas, aber es berechnet nichts. D.h. sein Rückgabetyp ist void:
interface IEnumerable<T>
{
void ForEach(???);
}
. Aber es fehlt noch etwas: der Schleifenkörper! Der Schleifenkörper ist eine Funktion. Genauer: er ist eine Prozedur, die keinen Wert zurückgibt (also eine Action). Aber sie bekommt einen Wert übergeben, nämlich das aktuelle Element, welches vom Typ T ist. Insgesamt sähe das ganze also so aus:
interface IEnumerable<T>
{
void ForEach(Action<T> body);
}
.

Ein anderes Beispiel wäre ein Filter, also eine Funktion, die alle Elemente eines IEnumerable<T> zurückgibt, auf die ein bestimmtes Prädikat zutrifft. In den meisten Sprachen heißt diese Methode filter, in Smalltalk und Ruby heißt sie select und in .NET heißt sie in Ahnlehnung an SQL Where. Wie muss ihr Typ aussehen? Nun, zunächst einmal gibt sie eine Untermenge der ursprünglichen Collection zurück, d.h. der Rückgabetyp muss derselbe sein wie this:
interface IEnumerable<T>
{
IEnumerable<T> Where(???);
}
Außerdem hatten wir ja gesagt, dass die Elemente auf Basis eines Prädikats gefiltert werden, also muss die Methode auch ein Prädikat übergeben bekommen:
interface IEnumerable<T>
{
IEnumerable<T> Where(??? predicate);
}
Und was ist der Typ des Prädikates? Nun, es muss einen Wahrheitswert zurückgeben, d.h. sein Rückgabetyp ist bool und da es einen Wert zurückgibt, ist es ein Func und kein Action. Zudem bekommt das Prädikat das aktuelle Element übergeben, also ein T:
interface IEnumerable<T>
{
IEnumerable<T> Where(Func<T, bool> predicate);
}
Eine mögliche Implementierung sähe so aus:
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>,
IList, ICollection, IEnumerable
{
List<T> Where(Func<T, bool> predicate)
{
var l = new List<T>;
foreach (var element in this)
{
if (predicate(element))
{
l.Add(element);
}
}
return l;
}
}
12.08.2010
Jörg W Mittag 571 2 4
2
Super erklärt ;-)
gfoidl 12.08.2010
1
Super erklärt, kleine Anmerkung noch zu folgendem Satz:
"Immer dann, wenn man einer Methode ein Stück ausführbaren Code als Argument übergeben will!" Hier könnte man noch auf das Vorhandensein von Delegates hinweisen und auf den Vorteil gegegenüber selbigen hinweisen.
Floyd 18.02.2011
2
Action<T> ist im Grunde genommen nur eine Vereinfachung um nicht dauernd delegates anlegen zu müssen. Also eine Art Standarddelegate.
Geht dann prinzipiell so (ungetestet und das was im MSDN Zitat von Mario gemeint ist):
private void Test(Action<int> callback)
{
int i = 42;
callback(i);
}

private void CallbackHandler(int intArg)
{
Console.Writeline("IntArg = " + intArg);
}

static void Main()
{
Test(CallbackHandler);
}

Im Übrigen gibt es bei dem MSDN 'Geblubber' auch Beispiele.
Hast Du den Link überhaupt mal geöffnet?
12.08.2010
DaSpors 4,2k 2 8
1
lt. MSDN
Sie können den Action(Of T)-Delegaten verwenden, um eine Methode als Parameter zu übergeben, ohne explizit einen benutzerdefinierten Delegaten zu deklarieren.Die gekapselte Methode muss der Methodensignatur entsprechen, die von diesem Delegaten definiert wird.Das bedeutet, dass die gekapselte Methode über einen Parameter verfügen muss, der als Wert übergeben wird. Außerdem darf kein Wert zurückgegeben werden.(In C# muss die Methode void zurückgeben.In Visual Basic muss sie durch das Sub…End Sub-Konstrukt definiert werden.Dies kann auch eine Methode sein, die einen Wert zurückgibt, der ignoriert wird.) Normalerweise wird eine solche Methode verwendet, um eine Operation auszuführen.


mfg
Mario
12.08.2010
Mario Priebe 6,0k 3 9
gfoidl 9,4k 3 5
Danke für die Antwort. Genau das Geblubber von MSDN hat mir aber überhaupt nicht weitergeholfen. Was heißt denn das nun? Was kann ich mit Action<T> machen. Könnt ihr ein Beispiel geben?
tack 12.08.2010
0
Vielen Dank an DaSpors, gfoidl, Mario Priebe und W. Mittag. Jetzt hab ichs kapiert.
12.08.2010
tack 294 1 8

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH