Chciałbym stworzyć pewną funkcję. Poglądowo wygląda ona tak
void CheckControls(ControlCollection kontrolki, Type typ, Function funkcja)
{
foreach(Control c in kontrolki)
{
if(c is typ)
{
funkcja(c);
}
if(c.HasChildren)
{
CheckControls(c.Controls);
}
}
}
Jednak aktualnie nie wiem jak użyć funkcji jako argumentu innej funkcji i jak użyć typu jako argument funkcji.
Kiedy on nie chce porównywać typów obiektów, lecz przekazać typ jako argument.
Sugerowałbym użyć metody generycznej zamiast podawać typ wśród argumentów.
void CheckControls(Control.ControlCollection collection)
{
foreach (Control c in collection)
{
if (c is T)
{
MessageBox.Show("Znalazłem!");
}
if (c.HasChildren)
{
CheckControls(c.Controls);
}
}
}
A co tak w ogóle chcesz osiągnąć? Bo na pierwszy rzut oka bez sensu jest wywoływanie metody jednocześnie z typem i zależnym od niego delegatem na metodę do wykonania. Nie lepiej byłoby skojarzyć typy z metodami w słowniku?
Szczerze mówiąc jedynie mi chodziło o to żeby np. wszystkie TextBoxy ukryć. Do tego potrzebowałem rekurencji (GroupBoxy, SplitContaintery itp) w połączeniu ze sprawdzaniem typu. A to z funkcją tak na momencie w trakcie zakładania tematu mi wpadło. Właśnie w takim celu jak wyżej wymieniłem
wszystkie(this.Controls, TextBox, ukryj).
Wiem, że to można by zrobić na zasadzie
ukryj(TextBox).
Ale jak mówię, to mi w chwili pisania tematu wpadło i z ciekawości to zostawiłem bo próbowałem przesłać funkcję jako argument i nie mogłem a teraz przynajmniej wiem gdzie szukać.
Pytanie, które postawił autor tematu jest błędne, ale to co chciał osiągnąć da się odczytać z wrzuconego przez niego kodu. Mam na myśli linijki if(c is typ) oraz Funkcja funkcja. Kod, który wrzuciłem jest jak najbardziej wystarczający, aby rozwiązać oba te problemy.
Z tego, co rozumiem, to chcesz to robić odwrotnie niż należy. Nie ma sensu pisanie uniwersalnej funkcji, a potem przekazywanie do niej jako argumentu funkcji, którą tamta funkcja ma wykonać.
Funkcja powinna robić jedną, konkretną rzecz. Jeśli chcesz ukrywać kontrolki danego typu, to napisz po prostu funkcję, która ukrywa kontrolki, np.:
void HideControls(Control.ControlCollection collection)
{
foreach (Control c in collection)
{
if (c is T)
{
c.Hide();
}
if (c.HasChildren)
{
HideControls(c.Controls);
}
}
}
Użycie:
this.HideControls(this.Controls);
Jeśli zachodzi potrzeba przekazania typu do funkcji, naturalnym i oczywistym wyborem wydają się metody generyczne. Dlatego, bo poza ładnym rozwiązaniem problemu pozwalają na nałożenie wymuszeń co do przekazywanych typów (klauzula where) i umożliwiają zabezpieczenie się przed błędami niezgodności typów już w czasie kompilacji. Jest to lepsze niż rozwiązanie w teorii oparte na typeof i is, a w praktyce na InvalidCastException i InvalidOperationException.
Nic, bo sam ich używam. Skąd pomysł, że mam coś przeciwko nim -,-? Mam wrażenie, że rozmawiamy o dwóch różnych rzeczach. Ja skupiłem się na kodzie, który wrzucił autor tematu, a Ty na samym tytule tematu
i stąd nieporozumienie. Zakończmy tą dyskusję, bo jest bezproduktywna.
Skorzystaj z możliwości jakie daje .NET Framework 3.5 i uzupełnij klasę kolekcji o nową metodę:
public static class ExtensionMethods
{
public static IEnumerable AllChildControls(this Control instance)
{
foreach (Control control in instance.Controls)
{
yield return control;
foreach (Control child in control.AllChildControls())
{
yield return child;
}
}
}
}