myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Basistechnologien und allgemeine .NET-Klassen » Objekt einer Oberklasse in ein Objekt einer Unterklasse casten
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Objekt einer Oberklasse in ein Objekt einer Unterklasse casten

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
derape
myCSharp.de-Mitglied

Dabei seit: 08.12.2009
Beiträge: 1


derape ist offline

Objekt einer Oberklasse in ein Objekt einer Unterklasse casten

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo zuammen,

meine Frage ist eher genereller Natur. Ich dachte eigentlich die OOP-Prinzipien verstanden zu haben Augenzwinkern
Hier meine Situation:

C#-Code:
private class BaseClass
{
  public int X;
}

private class ExtendedClass : BaseClass
{
  public int Y;
}

Eine einfache Basisklasse sowie eine abgeleitete Klasse. In meinem Fall ist die Basisklasse viel komplexer und ich moechte sie lediglich erweitern.

Ich habe nun ein Objekt der Basis klasse und moechte den Inhalt quasi auf die erweiterte Basisklasse kopieren.

C#-Code:
  BasisClass bc = new BasisClass();
  bc.X = 42;
  ExtendedClass ec = bc;

C# laesst hier keine implizite Konversion zu. Wenn ich versuche die Basisklasse zu der Extendedklasse zu casten bekomme ich einen null-Wert zurueck. Woran liegt das? Denn eigentlich enthaelt doch die Extendedklasse alle Informationen der Basisklasse...

Folgendes ginge (was ich nicht wirklich verstehe warum)

C#-Code:
  BasisClass bc = new ExtendedClass();
  (bc as ExtendedClass).Y = 44;

Jetzt muesste ich aber allerdings alle Eigenschaften der Klasse quasi auf die ExtendedClass kopieren...Gibt es auch einen "schnelleren" Weg wie im 2. Codebeispiel?

Vielen Dank im Vorraus
08.12.2009 02:43 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.457
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo derape,

ein Objekt ist immer vom Typ einer bestimmten Klasse und der Typ des Objekts ist nicht änderbar. Der Typ eines Objekts steht also fest. Bei Casten ändert man normalerweise nur den Typ des Ausdrucks, nicht den Typ des Objekts. Außerdem sind Variablen und Objekte zwei ganz unterschiedliche Paar Schuh. Du musst zwischen statischem Typ und dynamischen Typ einer Variablen unterscheiden.

Nach der Zuweisung

C#-Code:
BaseClass  bc = new ExtendedClass ();

ist die Variable, die den statischen Typ BaseClass hat, dann vom dynamischen Typ ExtendedClass, weil darin ein Objekt vom Typ ExtendedClass gespeichert ist. Die Zuweisung ändert aber weder was am Typ der Variablen noch was am Typ des Objekts.

Vererbung ist ein IST-EIN-Beziehung. Nehmen wir das beliebte Säugetier und Hund Beispiel. Ein Hund (Unterklasse) ist ein Säugetier (Oberklasse), aber ein Säugetier ist nicht zwangsläufig ein Hund. Deshalb geht deine Zuweisung nicht (verkehrte Richtung), auch mit einem Cast (der nur den statischen Typ einer eines Ausdrucks ändert) nicht.

Verabschiede dich von der Idee, dass du zur Laufzeit aus einem Objekt der Oberklasse ein Objekt der Unterklasse machen kannst. Das würde man zwar irgendwie hinbekommen (durch ein benutzerdefinierte Typumwandlung), aber das widerspricht den OOP-Prinzipien, nach denen der Typ eines Objekts zum Erzeugungszeitpunkt unwiderruflich festgelegt wird.

Noch ein Wort zu Variablen: Variablen vom Typ einer Klasse sind in C# Referenzvariablen. Das heißt, wenn ich geschrieben habe, eine Variable enthält ein Objekt, dann bedeutet das in Wahrheit, dass die Variable (nur) eine Referenz auf das Objekt enthält. Daran sieht man nochmal, dass Variablen und Objekte zwei ganz unterschiedliche Sachen sind.

herbivore
08.12.2009 07:05 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 8 Monate.
n4rF
myCSharp.de-Mitglied

Dabei seit: 03.09.2010
Beiträge: 1
Entwicklungsumgebung: VS 2008 Prof
Herkunft: Kelsterbach


n4rF ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Servus,

bin bei Internet Recherche über diesen Thread gestolpert da ich ein ähnliches Problem hatte und wollte einfach mal mein eLösung präsentieren

Mein Problem war, dass ich Objekte von einem WCF Service erhalte, die ich um einige Properties zwecks Anzeige erweitern musste.
Da ich nicht jedes Property einzeln der Subklasse zuweisen wollte habe ich als eleganteste Lösung Reflektion gewählt.

C#-Code:
class BaseClass
{
    public int x;
}

class ExtendedClass : BaseClass
{
    public int y;

    public ExtendedClass(BaseClass baseClass)
    {
        PropertyInfo[] Properties = baseClass.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

        for(int i = 0; i < Properties.Length; i++)
        {
            PropertyInfo propertyInfo = Properties[i];
            var value = propertyInfo.GetValue(baseClass, null);
            if(value != null)
            {
                propertyInfo.SetValue(this, value, null);
            }
        }
}

Hoffe das es jemanden weiterhelfen kann.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von n4rF am 03.09.2010 15:34.

03.09.2010 15:32 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 8 Jahre.
fieseskleinesMertel fieseskleinesMertel ist männlich
myCSharp.de-Mitglied

Dabei seit: 25.06.2019
Beiträge: 2
Entwicklungsumgebung: Microsoft Visual Studio
Herkunft: Deutschland


fieseskleinesMertel ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Leute,

ich bin ganz neu hier und habe ein Problem bei einer Belegarbeit für Info (Teil von meinem Maschinenbaustudium). Ich suche schon seit ungefähr einer Stunde nach einer praktikablen Lösung, aber finde leider nichts (weder die interne Suche noch google hat mich bisher weiter gebracht).
Bitte nehm mir nicht übel, dass ich so einen alten Thread ausgrabe, aber ich wollte nich unbedingt einen neuen aufmachen und dachte, dass das hier reinpasst. Es geht um eine abstrakte Oberklasse und deren Unterklassen. Das Problem besteht darin, dass ich mittels try-catch eine Variable vom Typ der abstrakten Oberklasse in eine Variable vom Typ der Unterklasse schreiben will und dafür einen praktikablen Weg suche.

Hier kommen die Details:

Das Framework dieses Projektes stellt mir eine abstrakte Oberklasse.

C#-Code:
public abstract class Oberklasse
{
    //Member der Oberklasse
    private string name = null;

    public string GetName();    //Gibt den Namen des Objektes. Der Name wird im Konstruktor festgelegt.
}

Von dieser Oberklasse habe ich mehrere Unterklassen abgeleitet.

C#-Code:
public class Unterklasse1 : Oberklasse
{
    //Member der Unterklasse1
}

public class Unterklasse2 : Oberklasse
{
    //Member der Unterklasse2
}

public class Unterklasse3 : Oberklasse
{
    //Member der Unterklasse3
}

An einer anderen Stelle habe ich eine Funktion. Diese Funktion bekommt als Argument eine Liste vom Typ Oberklasse, die also Objekte aller Unterklassen enthalten kann. Aus dieser Liste sollen jetzt alle Objekte vom Typ Unterklasse3 gesucht und als Liste zurückgegeben werden. Ich kann diese Funktion auch nicht grundsätzlich umgehen, da die Liste "oberliste" vom Framework vorgegeben wird und ich den entsprechenden Rückgabewert für das Programm brauche.
Im Moment habe ich das folgendermaßen gelöst:

C#-Code:
public List<Unterklasse3> SucheObjekteDerKlasse3(List<Oberklasse> oberliste)
{
    List<Unterklasse3> unterliste = new List<Unterklasse3>;
    try
    {
        foreach (Unterklasse3 unterobjekt3 in oberliste)
            unterliste.Add(unterobjekt3)
    }
    catch (InvalidCastException)
    {
        //In diesem Fall stimmt er Typ nicht überein und es soll nichts passieren.
    }
    return unterliste;
}

Das Problem an dieser Umsetzung ist natürlich, dass das foreach nach der ersten Exception abgebrochen wird. Wenn also als allererstes in der Liste ein Objekt vom Typ Unterobjekt1 steht, ist der Rückgabewert eine leere Liste.

Ich habe auch schon probiert, ob ich das über eine for-Schleife lösen kann:

C#-Code:
...
    for (int i = 0; i < oberliste.Count; i++)
    {
        try
        {
            unterliste.Add(oberliste[i]);//wird vom Debugger nicht zugelassen
        }
        catch (InvalidCastException)
        {  }
    }

Aber bei dieser Umsetzung kann ich gar nicht kompilieren, weil der Debugger rummeckert, weil die Typen von oberliste und unterliste nicht übereinstimmen.

Weiß jemand von euch zufällig eine Möglichkeit, wie ich diese Funktion umsetzen kann? Ich habe lange gesucht, wie ich eine Variable ok vom Typ Oberklasse in eine Variable uk3 vom Typ Unterklasse3 schreiben kann. Theoretisch müsste das ja möglich sein, wenn das in ok gespeicherte Objekt vom Typ Unterklasse 3 ist, aber der Debugger lässt das leider auch dann nicht zu, wenn ich die InvalidCastException abfange.

Ich habe auch gesucht wie ich try-catch und foreach sinnvoll kombinieren kann, aber das ist in diesem Fall scheinbar nicht möglich. Wenn ich das try-catch in die foreach-schleife schreibe, passiert während der Laufzeit ein Fehler, was ja auch klar ist.

Falls mir keiner eine Lösung aufzeigen kann, werde ich diese Unterscheidung über den Namen der Objekte durchführen. Theoretisch sind die Objekte nach ihrem Typ benannt, heißen also in etwa "Unterklasse1_03" oder "Unterklasse3_42". Praktisch werden die Namen durch eine Konfigurationsdatei vorgegeben, und wenn sich jemand nicht an diese Namenskonvention hält (z.B. ein fieser Korrektor beim Bewerten), kann das auch wieder zu Problemen führen. Deswegen würde ich einen eleganteren Weg bevorzugen.
25.06.2019 17:17 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Taipi88 Taipi88 ist männlich
myCSharp.de-Mitglied

avatar-3220.jpg


Dabei seit: 02.02.2010
Beiträge: 944
Entwicklungsumgebung: VS 2010
Herkunft: Mainz


Taipi88 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi,

hier gibt es verschiedene Wege zum Ziel.

Grundlegend wirst du casten müssen, casten tut man grundlegend so:

C#-Code:
var mySubObj = (MySubClass)myObj;

(Auch hierbei tritt eine Exception auf, wenn das Objekt eben keine Instanz von MySubClass ist)

Um nun vorab zu prüfen, ob so ein Cast überhaupt möglich ist - verwendet man den "is"-Operator, also:

C#-Code:
if (myObj is MySubClass)
{
var mySubObj = (MySubClass)myObj;
}

Ich denke den Schleifenteil kriegst du dann schon hin.

LG

PS: Für die Zukunft - bitte trotzdem einen neuen Thread pro Frage öffnen - so zwingst du nur einen Mod es manuell abzuteilen - also unnötige Arbeit.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Taipi88 am 25.06.2019 17:31.

25.06.2019 17:30 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
CoLo
myCSharp.de-Mitglied

Dabei seit: 25.09.2009
Beiträge: 223


CoLo ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

oder

C#-Code:
SomeClass someObject = obj as SomeClass;
if (someObject != null)
{
  //Cast erfolgreich
   ...
}
25.06.2019 17:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
witte
myCSharp.de-Mitglied

Dabei seit: 03.09.2010
Beiträge: 815


witte ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

C#-Code:
oberliste.Where(p => p is Unterklasse3).Cast<Unterklasse3>().ToList();
25.06.2019 18:34 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
fieseskleinesMertel fieseskleinesMertel ist männlich
myCSharp.de-Mitglied

Dabei seit: 25.06.2019
Beiträge: 2
Entwicklungsumgebung: Microsoft Visual Studio
Herkunft: Deutschland


fieseskleinesMertel ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Vielen Dank für die extrem schnellen Antworten, das war echt hilfreich. Ich habe es so gemacht, wie es Taipi vorgeschlagen hat, und habe dadurch wieder ein bisschen was gelernt.

Vielen Dank dafür.

Edit: Dass ich den Mods damit Arbeit mache, tut mir ehrlich gesagt leid. Das war mir nicht bewusst.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von fieseskleinesMertel am 25.06.2019 21:09.

25.06.2019 21:08 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 9 Jahre.
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 18.07.2019 00:42