Laden...

Welches Objekt habe ich?

Erstellt von Pedro_15 vor 18 Jahren Letzter Beitrag vor 18 Jahren 4.902 Views
P
Pedro_15 Themenstarter:in
375 Beiträge seit 2005
vor 18 Jahren
Welches Objekt habe ich?

Hallo, Wie kann ich ermitteln welches Objekt ich gerade bekommen habe?

z.b. ich bekomme ein Object übergeben. Wie kann ich ermitteln ob es sich um ein String handelt?

Gab es da nicht so etwas wie InstanceOf?

Danke für die Hilfe!

Pedro

P
939 Beiträge seit 2003
vor 18 Jahren

Du suchst wahrscheinlich den is-Operator. Entspricht dem instanceof-Operator von Java.

if(obj is ArrayList) {
}
P
Pedro_15 Themenstarter:in
375 Beiträge seit 2005
vor 18 Jahren

Danke!

Pedro

P
Pedro_15 Themenstarter:in
375 Beiträge seit 2005
vor 18 Jahren
Welche Object in SortedList

Hallo nach eine Nachtragsfrage.

ich habe eine Sortedlist mit verschiedenen Objekttypen.

Ich würde jetzt gerne eine Methode schreiben, der ich die SortedList übergebe und ein Objekttyp. als ergebnis würde ich gerne eine SortedList bekommen, wo nur die Object eingefügt sind vom übergenen Objecttyp.

z.B.
SortedList mit 12 int, 13 string usw.

methode(sortedlist, int)

Ergebnis 12 int in sortedlist

Ist das möglich?

Pedro

1.271 Beiträge seit 2005
vor 18 Jahren

Ja das müsste gehen. Ich habe mal ein Beispiel geschrieben, das überprüft, ob ein Objekt von einem bestimmten Typ ist:

private bool test(object obj,Type type){
	return type.IsInstanceOfType(obj);
}

Gibt aber auch true zurück, wenn obj die Instanz einer Klasse ist, die von type geerbt hat/abgeleitet ist!
Das müsstest du halt für dich entsprechend umbauen. Vielleicht gibt es aber auch noch eine andere/bessere Methode.

Gruß,
progger

A wise man can learn more from a foolish question than a fool can learn from a wise answer!
Bruce Lee

Populanten von Domizilen mit fragiler, transparenter Außenstruktur sollten sich von der Translation von gegen Deformierung resistenter Materie distanzieren!
Wer im Glashaus sitzt, sollte nicht mit Steinen werfen.

S
8.746 Beiträge seit 2005
vor 18 Jahren

Tja, du prüfst mit "is" wie gehabt, aber gegen eine Parametervariable vom Typ "Type". Beim Aufruf musst du typeof(int) anstellt von int angeben.

P
Pedro_15 Themenstarter:in
375 Beiträge seit 2005
vor 18 Jahren

Danke.

habe es jetzt so umgesetzt.


public SortedList getObjectList(Type type) 
{
	SortedList tempList = new SortedList();
	for (int i = 0, s = _sortedList.Count; i < s; i++) 
	{
		
		if (!(type.IsInstanceOfType(_sortedList.GetByIndex(i))))
		{
			continue;
		}
		tempList.Add(_sortedList.GetKey(i),_sortedList.GetByIndex(i));
	}
	return tempList;
}



getObjectList(typeof(int));

Danke!

Pedro

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Pedro_15,

nichts gegen deinen Code (auch wenn ich foreach statt for nehmen würde), aber wie kommt es, dass in der List so unterschiedliche Objekttypen enthalten sind? Könnte ein Hinweis auf schlechtes Design sein und wenn du uns die Umstände schilderst, dann habe wir vielleicht eine bessere Lösung für dich.

herbivore

4.221 Beiträge seit 2005
vor 18 Jahren

Obwohl ich nicht weiss wofür man so was braucht

GuckstDu: SortedList.GetIndexOfValue(type)

Wenn der Wert >-1 ist dann hast Du den Index und kannst damit den Key ziehen (der Wert ist ja type)

Oder was willst Du bezwecken...

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

P
Pedro_15 Themenstarter:in
375 Beiträge seit 2005
vor 18 Jahren

Danke für die Antworten.

@herbivore

Ok ich probiere es mal zu schildern, was ich mache.

Ich habe eine abstrakte Klasse Dokument, von der Leite ich Worddokument und Exceldokument ab. (Beispiel einwenig geändert)

Jetzt lese ich ein Verzeichnis ein und ermittle um welches Dokument es sich handelt und erzeuge eine Instanze z.B. Worddokument und schreibe sie in die SortedList.

Im allgemeinen greife ich das Objekt in der Liste immer über Dokument ab.
Jetzt will ich aber alle ExcelDokument aus der Liste oder alle WordDokumente.

Ich könnte ja in der Schleife auf eine Methode aus Dokument zugreifen und den DokumentenType ermitteln und damit selektieren. Aber ich dachte es ist besser auf die objektdefinition zuzugreifen.

Für Designvorschläge bin ich immer zu haben.

Danke Pedro!

PS: foreach ist eine super idee, irgenwie vergesse ich das immer.

4.506 Beiträge seit 2004
vor 18 Jahren

Hallo Pedro_15!

Ich glaube Herbivore möchte in Deinem konkreten Fall darauf hinaus, dass Du schon beim Einlesen der versch. Dokumente diese in versch. Listen packen solltest. Also lies alle *.doc und pack sie in ListeDoc, lies alle *.xls und pack sie in ListeExcel usw...

Dann brauch man hinterher auch nicht erst sortieren, oder suchen, und das Prg. läuft wahrscheinlich schneller.

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

P
Pedro_15 Themenstarter:in
375 Beiträge seit 2005
vor 18 Jahren

Hallo norman_timo,

ich glaube das ist keine gute Idee. Denn

  1. Ich verwende so nur eine Liste von Dokumenten in meinem System.
  2. Wenn ein neuer Objecttyp hinzukommt, brauche ich nur eine neue Dokumenten Klasse erstellen und beim einlesen berücksichtigen. Fertig. Wenn ich für jedes Dokumentenklasse eine eigene Liste aufbaue, ist es schwierig die neue Liste anzusprechen ohne denn ganzen Code zu überarbeiten.

Aber was sagen die anderen dazu?

Pedro

4.506 Beiträge seit 2004
vor 18 Jahren

Hallo Pedro_15!

Und wenn Du die Liste in der Dokumenten Klasse hälst?

So eine Art Dokumentencontainer?

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

S
1.047 Beiträge seit 2005
vor 18 Jahren

Ist halt die Frage wie Aufwendig diese Typevergleichen ist...

Ich hätte die Unterscheidung warscheinlich mit einem enum gemacht:

enum DocumentType {
Word,
Excel
}

wobei dann deine Basisklasse Dokument ein entsprechendes abstraktes get-Property vom Typ DocumentType bekommt, und in den Unterklassen entsprechend zurück gegeben wird.

Dann könntest du darüber die Unterscheidung machen.

Hast du ja auch schon beschrieben 🙂

Bei deiner Liste kannst du noch Generics benutzen, falls du .Net 2.0 hast (Typ Dokument)

S
8.746 Beiträge seit 2005
vor 18 Jahren

Das Halten Elemente verschiedener Typen in einer gemeinsamen Liste ist nicht das Problem - im Gegenteil. Eine Liste je Typ ist genauso schlecht wie ein Typvergleich auf einer Liste. Das Problem ist der Typvergleich selbst. Manuelle Typprüfung ist fast immer ein Zeichen schlechten OO-Designs. Hier sollten entsprechende Interfaces helfen auf jegliche Art von Typvergleich zu verzichten.

Der Nachteil eines manuellen Typvergleichs liegt in der Änderungsanfälligkeit. Bekommst du einen weiteren Typen in die Liste, so musst du den Listencode anfassen, d.h. einen weiteren Typvergleich hinzufügen (bei der Mehr-Listen-Version müßte eine weitere Liste angelegt werden, im Prinzip noch schlechter).

Löst du das mittels Interfaceimplementierung, so ist keinerlei Codeanpassung nötig. Genau das unterscheidet gutes von schlechtem Design: Robustheit und Flexibilität gegenüber Änderungen.

S
1.047 Beiträge seit 2005
vor 18 Jahren

@svenson
ok, dann wäre demzufolge pedros bisheriger ansatz genau richtig 🙂

hast du da mal ein beispiel was deiner meinung nach gutes design wäre?

S
8.746 Beiträge seit 2005
vor 18 Jahren

Definiere ein Interface, welches die Methoden definiert, die auf den Listenelementen ausgeführt werden sollen. Halte in der Liste nur noch Interfaces, keine Objekte mehr. Rufe Interface-Methoden anstelle der Objekt-Methoden auf und nutze dazu Polymorphie.

Beispiel: Je nach Typ soll eine völlig andere Methode ausgeführt werden, einmal drucken, einmal speicher, whatever.

Definiere eine Listeninterface und genau eine Methode namens DoListOperation(). Implementiere DoListOperation() einmal als Drucken, Speichern, etc.!

Fertig. Kein Typvergleich, einfach Element aus der Liste holen und DoListOperation() aufrufen.

Noch dynamischer: Implementiere anstelle DoListOperation() auf dem Interface eine Methode (GetListOperation()), die einen Delegaten zurückliefert, den du aufrufen kannst (Strategie-Pattern). Nun kann für jede Klasse von außen (z.B. über ein XML-File) konfiguriert werden, welche Methode aufgerufen wird.

S
1.047 Beiträge seit 2005
vor 18 Jahren

@svenson
achso, sowas meintest du... ok, das ist ja klar.

ich seh auch, was das problem bei meiner idee wäre:
wenn ich einen neuen dokumententyp häte, müßte ich das enum anpassen 😕

aber ansonsten spricht ja nix dagegen, oder hab ich nochwas übersehen?

Noch dynamischer: Implementiere anstelle DoListOperation() auf dem Interface eine Methode (GetListOperation()), die einen Delegaten zurückliefert, den du aufrufen kannst (Strategie-Pattern). Nun kann für jede Klasse von außen (z.B. über ein XML-File) konfiguriert werden, welche Methode aufgerufen wird.

nur mal der interesse halber:
was genau müßte denn die methode zurück geben?

weil du das thema "über xml" angesprochen hast, würde ich vermuten einen string, der den methodennamen oer sowas anthält, den ich dann über refleection aufrufe?

oder wie?

4.506 Beiträge seit 2004
vor 18 Jahren

Hallo nochmal!

Jetzt ist halt die Frage, wieviele "alte" Klassendefinitionen sind bereits vorhanden und wieviele werden da noch dazu kommen?

Ich kann Dir nur vollkommen Recht geben, Svenson, das mit der Mehr-Listen-Variante ist nix für gutes Design.

Ich hab das mal unter dem Aspekt Quick-And-Dirty betrachtet, und je nachdem wieviel Aufwand betrieben werden darf/kann/soll, ist natürlich zu entscheiden, ob ich das in Deiner vorgeschlagenen Variante nachziehe, oder ob ich eine Q-and-D Lösung bevorzuge.

Aber das muss hier jeder selbst entscheiden.

Du hast aber Recht, da er nach Design-Aspekte gefragt hatte, wäre es wohl besser gewesen erst mal genau darüber nachzudenken 🙂

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von sheitman
ich seh auch, was das problem bei meiner idee wäre:
wenn ich einen neuen dokumententyp häte, müßte ich das enum anpassen 😕

Genau. Ob du nun einen Typ mit "is" vergleichst, oder ein Typ-Enum einführst, ist gehuppt wie gesprungen.

nur mal der interesse halber:
was genau müßte denn die methode zurück geben?

Das hängt natürlich davon ab, was aus Sicht der Liste sinnvoll ist. Kann ich ohne Kenntniss deines Codes nicht sagen. In den meisten Fällen dürfte es aber eine void-Funktion werden.

weil du das thema "über xml" angesprochen hast, würde ich vermuten einen string, der den methodennamen oer sowas anthält, den ich dann über refleection aufrufe?

Noch besser wäre etwas anderes: Du lagerst diese Funktion in eine weitere Klasse aus. Auf diese greifst du wiederum via Interface zu. Wenn du diese Klasse in ein eigenes Assembly packst, kannst du zur Laufzeit entscheiden, welches Implementierung du benutzen willst. Du hast damit quasi eine PlugIn-Architektur geschrieben. Welches konkretes Assembly du lädst konfigurierst du in einer XML-Datei.

Du kannst nun nicht nur zwischen Methoden per Konfiguration umschalten, sondern sogar durch einfaches Einkopieren weiterer DLLs weitere Funktionen hinzufügen. Wunderbares Konzept, z.B. für Speichern in verschiedenen Formaten (Export-Plugins).

Um es nochmal zu betonen: Mit einigen wenigen Ausnahmen ist "is" immer ein Zeichen schlechten Designs. Manchmal ist das vertretbar, wenn sich das auf einen kleinen abgeschotteten Teil des Codes bezieht. Statt hier mit zusätzlichen Interfaces und Klassen zu hantieren geht man den "kurzen Weg". Wenn man z.B. genau weiss, dass sich an der Zahl der Typen niemals was ändern wird, dann ist das vertretbar, obwohl man sich bewußt sein sollte, dass "niemals" oder "immer" Begriffe sind, die in der professionellen Softwareentwicklung mit Vorsicht zu geniessen sind (niemals ist die Zeitspanne bis zum gegenteiligen Wunsch des Kunden).

"is" ist notwendig, wo man z.B. schlechtes Design nutzen muss, oder bei bestimmten generischen Ansätzen. In fachlichem Code hat "is" aber nie was zu suchen.

P
Pedro_15 Themenstarter:in
375 Beiträge seit 2005
vor 18 Jahren

Hallo,

Ich habe eine abstrakte Klasse Dokument, von der Leite ich Worddokument und Exceldokument ab.

@svenson
Dann finde ich meinen Ansatz doch gar nicht so schlecht. Den die abstrakte Klasse ist doch fast wie dein Interface. Ich muss aber dazu sagen, dass das Interface noch nicht mein Freund ist und komme damit im OOP Design noch nicht richtig klar.

Ich spreche bei mir im gesamten Code nur die Dokumenten Teil des Objektes an.
Leider kam jetzt bei einem spez. Dokumenten Type eine Eigenschaft dazu. Die habe ich in der Abgeleiteten Klasse eingefügt. Bei einer Funktion brauch ich jetzt diesen Objekttyp mit der Eigenschaft, deswegen meine Frage nach der Erkennung welches Objekt ich habe.

Vielleicht kannst du noch etwas dazu sagen, wie du das Problem gelöst hättest.

Danke Pedro

N
4.644 Beiträge seit 2004
vor 18 Jahren

Mit Interfaces erreichst Du aber eine losere Kopplung.
Such mal im Forum nach Microkernel oder evtl. Contract First.

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo norman_timo,

Ich glaube Herbivore möchte in Deinem konkreten Fall darauf hinaus, dass Du schon beim Einlesen der versch. Dokumente diese in versch. Listen packen solltest.

Nein, ich meinte es so wie sevenson es in seinem ersten Beitrag schreibt.

Hallo Pedro_15, hallo Noodles,

ich bin eh nicht so ein Interface-Fan. Deshalb finde ich die Lösung mit der abstrakten Klasse voll ok. Aber auch ohne meine Vorliebe, ist vom Design her hier eine abstrakte Klasse wohl das Passendere.

herbivore

S
8.746 Beiträge seit 2005
vor 18 Jahren

Wenn die angedeutete Flexibilität nicht erforderlich ist, spricht auch nichts gegen eine abstrakte Oberklasse. Hauptsache man ist sich der potentiellen Nachteile bewußt und kann sicher sein, dass sie in diesem Szenario keine Rolle spielen.

4.221 Beiträge seit 2005
vor 18 Jahren

Eine Kombination aus Beidem ist oftmals die beste Lösung....

Ein Interface erstellen.
Eine Basisklasse erstellen welche das Interface implementiert. Diese Klasse implementiert somit das Default-Verhalten des Interfaces.

Programmiert wird gegen das Interface.

Nun leiten die ersten paar Klassen alle von dieser Basisklasse ab.... Wenn man an den Punkt gelangt wo eine Ableitung nicht möglich ist erstellt man eine neue Klasse welche das Interface implementiert.... diese ist dann (weil nur gegen Interface programmiert wurde) sofort lauffähig.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...