Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Wie kann ich eine Klasse als Methoden-Parameter in Methode übergeben?
CrocodileDundee
myCSharp.de - Member



Dabei seit:
Beiträge: 54

Themenstarter:

Wie kann ich eine Klasse als Methoden-Parameter in Methode übergeben?

beantworten | zitieren | melden

Hallo zusammen,
ich möchte einer Methode einen Klassennamen als Parameter übergeben.
Also praktisch folgendermaßen:


public class Auto()
{
     ...
}

public class Person()
{
     ...
}


public class TuWasMitDerKlasse(Klasse) 
{
     ...
}

Die Klasse "TuWasMitDerKlasse" bekommt in diesem Fall also entweder "Auto" oder "Person" als Parameter übergeben.

Habs schon versucht mit


public class TuWasMitDerKlasse(typeof(Klasse)) 
{
     ...
}

oder mit


public class TuWasMitDerKlasse(class Klasse) 
{
     ...
}

Geht beides nicht. Kann mir jemand vielleicht eine Tipp geben?

Danke und Gruß
Frank
private Nachricht | Beiträge des Benutzers
BhaaL
myCSharp.de - Member

Avatar #erP6yAFiewXrJTqrvg6R.jpg


Dabei seit:
Beiträge: 655

beantworten | zitieren | melden

Bist du eventuell auf der Suche nach Generics?

An der Stelle aber der Hinweis: Nur weil du etwas generisch machen kannst, heißt das nicht notwendigerweise, dass du es auch generisch machen solltest. Aber das kannst du nur selbst aufgrund deiner Anforderungen feststellen.
private Nachricht | Beiträge des Benutzers
inflames2k
myCSharp.de - Experte

Avatar #AARsmmPEUMee0tQa2JoB.png


Dabei seit:
Beiträge: 2340

beantworten | zitieren | melden

Die wichigste Frage ist ja, was du erreichen möchtest. Was soll denn in TuWasMitDerKlasse passieren?
Willst du eine Instanz übergeben oder tatsächlich nur den Typ?


public class TuWasMitDerKlasse(Klasse)

Das ist im übrigen alles, nur keine gültige Notation zur Definition einer Klasse.

Wie BhaaL gehe ich davon aus, dass du nach Generics suchst. Also etwas in der Richtung:


public class TuWasMitDerKlasse<TKlasse>
{
     public TuWasMitDerKlasse(TKlasse klasse)
     {
     }
}

Allerdings erschließt sich mir nicht, was Auto und Person gemeinsam haben könnten, dass sie mit einer gemeinsamen Verarbeitungslogik verarbeitet werden könnten.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von inflames2k am .
Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager | Spielkartenbibliothek
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4001

beantworten | zitieren | melden

Generics machen aber nur Sinn, wenn die Klassen über eine gemeinsame Basisklasse (bzw. Interface) verfügen, ansonsten kann innerhalb der generischen Methode nur auf Methoden von Object zugegriffen werden.

Die andere Möglichkeit wäre (du warst schon fast auf dem richtigen Weg):


public void TuWasMitDerKlasse(Type type)
{
     ...
}
Und dann als Parameter typeof(Auto) übergeben - aber auch hier kannst du dann direkt nur auf Methoden der Klasse Type zugreifen, d.h. Reflection benutzen.

PS: Als Rückgabewert class bei der Methode zu benutzen, war hoffentlich nur ein Schreibfehler (und kein Verständnisfehler)?!
private Nachricht | Beiträge des Benutzers
Coffeebean
myCSharp.de - Team

Avatar #avatar-3295.gif


Dabei seit:
Beiträge: 2459
Herkunft: Deutschland/Schweiz

beantworten | zitieren | melden

Hallo CrocodileDundee,

vielleicht verstehe ich die Sache auch falsch, aber wieso kannst du nicht ein Interface nehmen und das als Parameter übergeben?


public interface IIrgendwas
{
	TuEtwas();
}

public class Auto : IIrgendwas
{
    TuEtwas() { ... }
}

public class Person()
{
   TuEtwas() { ... }
}


public class TuWasMitDerKlasse(IIrgendwas klasseDieInterfaceImplementiert)
{
    klasseDieInterfaceImplementiert.TuEtwas();
}

Reflection würde ich nicht einsetzen, wenn du es nicht musst.

Gruss

Coffeebean
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15705
Herkunft: BW

beantworten | zitieren | melden

Im Fall des Interfaces wäre aber das besser

public void TuWasMitDerKlasse<T>(T klasseDieInterfaceImplementiert) where T: class, IIrgendwas
private Nachricht | Beiträge des Benutzers
panicJonny
myCSharp.de - Member



Dabei seit:
Beiträge: 69

beantworten | zitieren | melden

Huhu, das ist keine ketzerische Frage sondern ernst gemeint. Warum das als generic übergeben?
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15705
Herkunft: BW

beantworten | zitieren | melden

Das "besser" war aus dem Auge als Software Architekt.
Gründe zB Why use constraints

Du kannst eben auf ein Generic Einschränkungen setzen, die eben bei einfacher Parametrisierung nicht möglich sind.
private Nachricht | Beiträge des Benutzers
panicJonny
myCSharp.de - Member



Dabei seit:
Beiträge: 69

beantworten | zitieren | melden

hm,

die brauche ich aber auch nicht, wenn ich den Parameter vom Typ IIrgendwas mache.

Welchen Vorteil bekomme ich davon statt

void foo(IIrgendwas param)

void foo<T>(T param) where t: class, IIrgendwas

zu machen?

Das ist, für mich gesehen, der gleiche Aufruf nur komplizierter
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von panicJonny am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15705
Herkunft: BW

beantworten | zitieren | melden

Zitat von panicJonny
hm,
die brauche ich aber auch nicht, wenn ich den Parameter vom Typ IIrgendwas mache.

Schau Dir bitte den Link an und wie Generics funktionieren.
Das ist eben auch ein Thema von Software Design.

    public class A
    {
        public void Test()
        {
            IIrgendwas a = new Etwas();
            Etwas b = new Etwas();

            TuWasMitDerKlasse(a);
            TuWasMitDerKlasse(b);
        }

        public void TuWasMitDerKlasse(IIrgendwas klasseDieInterfaceImplementiert) {}
        public void TuWasMitDerKlasse<T>(T klasseDieInterfaceImplementiert) where T : class, IIrgendwas { }
    }

Die Übergabe mit A ruft die Methode mit Interface als Parameter auf.
Die Übergabe mit B eben die Methode mit Interface über die generische Einschränkung auf.

Fällt Dir was auf? :-)
Zitat
der gleiche Aufruf nur komplizierter
Das ist eine subjektive Aussage (ähnlich wie mein "Besser" ohne Erklärung ;-)
private Nachricht | Beiträge des Benutzers
panicJonny
myCSharp.de - Member



Dabei seit:
Beiträge: 69

beantworten | zitieren | melden

Sorry, kantische Lehrmethoden funktionieren bei mir heute nicht.

Was ist der Benefit davon, dass ich den Aufruf über ein Generic mache? Und bitte nicht wieder auf den Artikel mit den contstaints verweisen. Der hat mit meiner Frage irgend wie nichts zu tun.

Grüße
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15705
Herkunft: BW

beantworten | zitieren | melden

Naja; nur weil Du jetzt keine Lust einen Artikel zu lesen, der *genau* Deine Frage behandelt oder Dich mit Generics und deren Hintergrund nicht beschäftigen magst, springe ich noch lange nicht - nur weil Du schreist ;-)
Wenn für Dich das mit den Generics keinen Sinn macht: okay, kann ich mit leben.
Nutzbar ist hier beides. Mein Hinweis es auf positive Art zu Nutzen, gerade was die Möglichkeiten und Erweiterbarkeiten betrifft, der bleibt.

Viel Erfolg :-)
private Nachricht | Beiträge des Benutzers
panicJonny
myCSharp.de - Member



Dabei seit:
Beiträge: 69

beantworten | zitieren | melden

Ich hab mir aus "Verzweiflung" noch mal deine erste Antwort langsam durchgelesen und bin auf diesen Satz gestoßen.
Zitat von Abt
Das "besser" war aus dem Auge als Software Architekt.

Du kannst eben auf ein Generic Einschränkungen setzen, die eben bei einfacher Parametrisierung nicht möglich sind.


Dein Aufruf startet quasi mit einer Whitelist und schränkt diese dann nachträglich ein (bildlich gesprochen).

Das Interface als Parameter anzugeben schränkt hingegen gleich maximal ein. Was ja an der Stelle für mich Sinnvoll zu sein scheint.

Das enzige, was mir an der Stelle dazu einfällt ist Erweiterbarkeit, falls ich mal ein weiteres Interface supporten soll. Allerdings soll man ja seine Software auch nicht auf absolut jeden möglichen Fall auslegen (overengineering).
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von panicJonny am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15705
Herkunft: BW

beantworten | zitieren | melden

Zitat von panicJonny
iwarum DU das so vorgeschlagen hast. Warum denkst du, ist es besser ein Generic zu benutzen statt das Interface als Parameter zu nehmen.

Es ist ein grundlegendes Thema:
Zitat von Abt
Das ist eben auch ein Thema von Software Design.
Zitat von Abt
Du kannst eben auf ein Generic Einschränkungen setzen, die eben bei einfacher Parametrisierung nicht möglich sind.
Das "Grundproblem", dass die Leute keine Constraints kennen, aber kennen sollten.
Denn viele Dinge lassen sich über constraints viel einfacher lösen - zur Compile Zeit - während man immer wieder über Implementierungen stolpert, die instabil zur Laufzeit geprüft werden.
Prinzip: turning runtime errors into compile time errors.
Zusätzlich natürlich das Cast-Thema, zB. bei Rückgaben des Eingangsparameters bei solchen Methoden.
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4001

beantworten | zitieren | melden

Auch ich sehe hier keinen Vorteil in der generischen Variante. Beides wird vom Compiler zur Compile-Zeit geprüft.
Und auch die Einschränkung "class" ist bei Angabe eines Interfaces überflüssig, denn Interfaces funktionieren generell nur bei Klassen (nicht bei Strukturen).

Und worauf du, @Abt, mit deinem Code-Beispiel hinaus willst, kann ich auch nicht sehen?
private Nachricht | Beiträge des Benutzers
MarsStein
myCSharp.de - Experte

Avatar #avatar-3191.gif


Dabei seit:
Beiträge: 3429
Herkunft: Trier -> München

beantworten | zitieren | melden

Hallo,
Zitat von Th69
Und auch die Einschränkung "class" ist bei Angabe eines Interfaces überflüssig, denn Interfaces funktionieren generell nur bei Klassen (nicht bei Strukturen).
Nur zur Richtigstellung: Das stimmt nicht. Auch Strukturen können Interfaces implementieren, und dann auch in auf diese Interfaces eingeschränkten Generics benutzt werden.

Gruß, MarsStein
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4001

beantworten | zitieren | melden

Ups, hast recht - habe mich davon verleiten lassen, daß Strukturen keine Basisklassen haben können.
Jedoch gibt es wohl Boxing-Probleme damit: C#: structs and Interface

Meine Hauptfrage an Abt bleibt aber bestehen.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15705
Herkunft: BW

beantworten | zitieren | melden

Zitat von Abt
Das "Grundproblem", dass die Leute keine Constraints kennen, aber kennen sollten.
Denn viele Dinge lassen sich über constraints viel einfacher lösen - zur Compile Zeit - während man immer wieder über Implementierungen stolpert, die instabil zur Laufzeit geprüft werden.
Prinzip: turning runtime errors into compile time errors.
Zusätzlich natürlich das Cast-Thema, zB. bei Rückgaben des Eingangsparameters bei solchen Methoden.

Interface Methode(Interface x) {}
vs

T Methode<T>(T x) where T: Interface {}
Generics sind einfach enorm wichtige Bausteine in der Software Architektur von .NET. Sie bieten eine viel höhere Erweiterbarkeit.
Bei der Generic Variante bekomme ich den konkreten Typ zurück - beim Interface nicht.

Dann noch einfache Fakten, die mit meiner eigentlichen Intension von "Besser" nichts zutun hatten:
- Ich kann Klassen bzw. Erweiterungsmethoden ganz anders und optimaler gestalten
- (Achtung Micro-Optimierung): Der Aufruf des Generic ist i.d.R. schneller als über das Interface. Gibts zig Benchmarks und Artikel zu.
- Thema Boxing bei Value Types
- Der generische Weg gilt seit langem auch in vielen Büchern als "idiomatic"
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4001

beantworten | zitieren | melden

Mir ist klar, daß Generics einen Vorteil bilden können (gerade bei Factory-Methoden, welche einen konkreten Typ zurückgeben), in dem konkreten Fall

 public void TuWasMitDerKlasse(IIrgendwas klasseDieInterfaceImplementiert)
jedoch ist das eine typische Signatur von Dependency Injection Methoden (u.a. auch Konstruktoren) - und daher bin ich irritiert, wenn dies dann immer durch Generics ersetzt werden sollte.

Können wir uns darauf einigen, daß ein Entwickler beide Varianten kennen sollte und je nach Anwendungsfall (also z.B. wenn mehr als eine Constraint-Bedingung vorliegt) dann Generics bevorzugen sollte?
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15705
Herkunft: BW

beantworten | zitieren | melden

Zitat von Th69
und daher bin ich irritiert, wenn dies dann immer durch Generics ersetzt werden sollte.
Hat ja auch keiner gesagt.
Die Diskussion hat sich auch von meiner eigentlichen, spezifischen Aussage und dessen Hintergrund total verrannt; in meinen Augen - trotz mehrfacher Hinweise - weil man offenbar die Wirkung von Generics nicht bewusst ist und den Sinn nicht verstanden hat.
Daher bin ich auch raus.
private Nachricht | Beiträge des Benutzers
inflames2k
myCSharp.de - Experte

Avatar #AARsmmPEUMee0tQa2JoB.png


Dabei seit:
Beiträge: 2340

beantworten | zitieren | melden

Hallo CrocodileDundee,

war denn für dich schon etwas brauchbares dabei? Nur um mal zum Kern des Problems zurück zu kehren.
Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager | Spielkartenbibliothek
private Nachricht | Beiträge des Benutzers