C# und Objektoriertiertes proggen... J4nchu goes c# xD

Janchu88

Kapitän zur See , HWLUXX Vize-Superstar
Thread Starter
Mitglied seit
29.11.2005
Beiträge
5.271
Ort
irgendwo im Nirvana...
Hi,

da mein Buch endlich da ist (Visual C# 2005 von Andreas Kühnel) wühle ich mich gerade wieder durch die Grundlagen.

Nun wollte ich mich mal an nem simplen Objekt versuchen, also einfach drauf los... und irgendwas läuft gerade schief

nun meine Frage, was ist an den Methoden getcolor() und getname() verkehrt? (Weiter unten in der Klasse Auto) sie geben nämlich nix zurück... getspeed() ist genauso aufgebaut und läuft, der unten abgebildete code gibt folgendes aus:

Code:
 ist langsamer als das andere Auto
 ist schneller als das andere Auto

Eigentlich müsste da doch der name vorstehen!? Hier der Quellcode:

Code:
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            Auto karre = new Auto();
            Auto karre2 = new Auto();
            karre.setspeed(231);
            karre2.setspeed(431);
            karre.setname("BMW");
            karre.setname("Porsche");

            karre.comparespeed(karre2);
            karre2.comparespeed(karre);

            Console.ReadLine();
        
            

        }
    }

    public class Auto
    {
        public int geschwindigkeit;
        public string farbe;
        public string name;

        public void setspeed(int kmh)
        { geschwindigkeit = kmh; }

        public void setcolor(string farbe)
        { farbe = this.farbe;  }

        public void setname(string name)
        { name = this.name; }

        public void comparespeed(Auto m)
        {
            int eigenesauto;
            int zweitesauto;

            eigenesauto = geschwindigkeit;
            zweitesauto = m.getspeed();

            if (eigenesauto > zweitesauto)
            { Console.WriteLine(name + " ist schneller als das andere Auto"); }

            else if (eigenesauto == zweitesauto)
            { Console.WriteLine("Beide Autos sind gleich schnell"); }

            else
            { Console.WriteLine(name + " ist langsamer als das andere Auto"); }

        }

        public int getspeed()
        { 
            return geschwindigkeit; 
        }

        public string getcolor()
        { 
            return farbe; 
        }

        public string getname()
        {
            return name;
        }

        
    }


}
 
Zuletzt bearbeitet:
Wenn Du diese Anzeige nicht sehen willst, registriere Dich und/oder logge Dich ein.
Code:
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            Auto karre = new Auto();
            Auto karre2 = new Auto();
            karre.setspeed(231);
            karre2.setspeed(431);
            karre.setname("BMW");
            [b]karre2.setname("Porsche");[/b] //aber eher uninterresant

            karre.comparespeed(karre2);
            karre2.comparespeed(karre);

            Console.ReadLine();
        
            

        }
    }

    public class Auto
    {
        public int geschwindigkeit;
        public string farbe;
        public string name;

        public void setspeed(int kmh)
        { geschwindigkeit = kmh; }

        public void setcolor(string farbe)
        [b]{ this.farbe = farbe  }[/b] // und nicht farbe = this.farbe; 

        public void setname(string name)
        [b]{ this.name = name}[/b] // und nicht name = this.name; 

        public void comparespeed(Auto m)
        {
            int eigenesauto;
            int zweitesauto;

            eigenesauto = geschwindigkeit;
            zweitesauto = m.getspeed();

            if (eigenesauto > zweitesauto)
            { Console.WriteLine(name + " ist schneller als das andere Auto"); }

            else if (eigenesauto == zweitesauto)
            { Console.WriteLine("Beide Autos sind gleich schnell"); }

            else
            { Console.WriteLine(name + " ist langsamer als das andere Auto"); }

        }

        public int getspeed()
        { 
            return geschwindigkeit; 
        }

        public string getcolor()
        { 
            return farbe; 
        }

        public string getname()
        {
            return name;
        }

        
    }


}
 
Genau, mit der Korrektur von LisTenEr läufts.

Aber: ich würde keine Methoden wie getspeed() und setspeed() verwenden, und geschwindigkeit würde ich auch nicht so als public-Eigenschaft stehen lassen.

Hast du schon mal was von getter- und setter-Methoden gehört?
Dazu legst du zu jeder public-Eigenschaft noch eine private-Eigenschaft gleichen Typs an, die sich nur in der Groß-/Kleinschreibung unterscheiden.
Die public-Eigenschaft bekommt dann noch Methoden zum Setzen und Lesen der Eigenschaft.
Sinn des ganzen ist, man kann lesend und schreibend (oder nur lesend, wenn man den Setzen-Teil weglässt) auf die Eigenschaft zugreifen, und hat gleichzeitig die Möglichkeit, Prüfungen durchzuführen o.ä.

Sieht dann ungefähr so aus:
Code:
	public class Auto
	{
		private int geschwindigkeit;
		public int Geschwindigkeit
		{
			get { return this.geschwindigkeit;	}
			set { if (value > 0) this.geschwindigkeit = value; } //Negative Geschwindigkeiten sind sinnlos
		}

		private string farbe;
		public string Farbe
		{
			get { return this.farbe; }
			set { this.farbe = value; }
		}

		private string name;
		public string Name
		{
			get { if (this.name == null) return "Auto"; else return this.name; } //Bei leerem Namen Standardwert zurückgeben
			set { this.name = value; }
		}

		public void comparespeed(Auto m)
		{
			int eigenesauto;
			int zweitesauto;

			eigenesauto = this.Geschwindigkeit;
			zweitesauto = m.Geschwindigkeit;

			if (eigenesauto > zweitesauto)
			{ Console.WriteLine(this.Name + " ist schneller als das andere Auto"); }

			else if (eigenesauto == zweitesauto)
			{ Console.WriteLine("Beide Autos sind gleich schnell"); }

			else
			{ Console.WriteLine(this.Name + " ist langsamer als das andere Auto"); }
		}
	}

Wenn du dazu noch Fragen hast, immer her damit!

OT: Verdammt, was mach ich eigentlich um die Uhrzeit noch hier...:fresse:
 
wenn ich das richtig verstehe willst du die eigenschaften also als private deklarieren und nur den zugriff über die methoden erlauben?

Was mir noch nicht ganz eindeutig ersichtlich ist, wie würde der Zugriff das aussehen? Meine bescheidene Interpretation sieht so aus :

Code:
Auto karre = new Auto();
karre.Name.set("Fiat");
string x = karre.Name.get;

?

Sehe nämlich keinen Konstruktor der nen wert bei der set methode übergibt? Oder macht der das bei set automatisch?

PS: auf jeden Fall schonmal danke für die Hilfe ;)

edit: Nach der grandiosen Idee es mal einfach auszuprobieren ( :fresse: ), so wie ich meinte gehts leider net :/
 
Zuletzt bearbeitet:
Sorry, hatte ich vergessen dazu zu schreiben.
War ja auch schon spät. :fresse:

So muss das aussehen:
Code:
	Auto karre = new Auto();
	Auto karre2 = new Auto();
	karre.Geschwindigkeit = 231;
	karre2.Geschwindigkeit = 431;
	karre.Name = "BMW";
	karre2.Name = "Porsche";

Geschwindigkeit, Name und Farbe sind Eigenschaften, keine Methoden.
Das siehst du wenn du z.B. "karre." eingibst.
Und beim Setzen bzw. Lesen dieser Eigenschaften wir das ausgeführt was bei set bzw get steht.
geschwindigkeit, name und farbe halten hier den jeweiligen Wert intern.

Bei deinem Ansatz kann eine Eigenschaft auch direkt geändert werden, ohne deine setxy Methoden zu verwenden. Das ist hier nicht möglich.
Man kann Prüfungen einbauen, ob der Wert sinnvoll ist.
Auch kann man Eigenschaften als Read-Only deklarieren.

Hier mal ein kleines Beispiel, die Eigenschaft Flaeche kann nur gelesen werden, und für Breite und Laenge sind nur positive Werte erlaubt:
Code:
	public class Rechteck
	{
		private int laenge;
		public int Laenge
		{
			get { return this.laenge; }
			set { if (value >= 0) this.laenge = value; } // Nur positive Werte erlaubt
		}

		private int breite;
		public int Breite
		{
			get { return this.breite; }
			set { if (value >= 0) this.breite = value; } // Nur positive Werte erlaubt
		}

		public int Flaeche
		{
			get { return this.Breite * this.Laenge; }
			// Kein set{ }, Eigenschaft ist read-only
		}
	}
 
jetzt denke ich in etwa verstanden zu haben, thx ;)

bei weiteren fragen, stelle ich sie hier dann... :)

edit: Paar Seiten weiter gelesen @ Visual C# 2005... nun kommt die Thematik mit get und set... damit ist alles geklärt... :d

Hinzugefügter Post:

Btw, hier mal eine aktuelle Sache die ich umgesetzt hab... könnte man gerade in der fehlererkennung noch verbessern... aber das war nur so ne zwischendurch sache zum üben :)

hier der Quellcode, ist dazu da ne ganzzahl in binär/bit schreibweise umzuformen :xmas:

Code:
using System;
using System.Collections.Generic;
using System.Text;

namespace Binary
{
    class Program
    {
        static void Main(string[] args)
        {
            Bit code = new Bit();
            Console.WriteLine("Bitte geben sie einen positiven ganzzahligen Wert ");
            Console.Write("ein, der als Bitcode dargestellt werden soll: ");
            code.Dezimalwert = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine();
            code.WriteBitCode();
            Console.ReadLine();

        }
    }

    class Bit
    {
        private int dezimalwert;
        public int Dezimalwert
        {
            get 
            { return dezimalwert; }

            set
            {
                  if (value >= 0) 
                  { dezimalwert = value; }
                 
                  else
                  { Console.WriteLine(""); Console.WriteLine("Unzulässige Eingabe"); } 
            }

        }


        public void WriteBitCode()
        {
            int dezimal = dezimalwert;
            int bit;
            int teiler = 1;
            int rest;
            int counter = 0;

            

            //Ausgabe der Dezimalzahl und des Textes
            Console.Write(dezimal + " als Bitcode lautet: ");

            //Es wird mithilfe der Schleife ermittelt ab welcher 2er Potenz der BitCode beginnt 
            while (dezimalwert > teiler )
            {
                teiler *= 2;
                
                //Nebenbei wird gezählt wie oft der Teiler potenziert wird, um die letztendliche Länge des Bitcodes zu ermitteln
                counter++;
            }

            //Die Zählschleife erstellt pro Durchgang ein Zeichen des Bitcodes
            //Hier ist der Counter von Interesse, da er die Anzahl der Durchläufe bestimmt
            for(int i = 0;i<=counter;i++)
            {
                
                
                // Prüfung: Hat das aktuelle bit den Wert 1 oder 0?
                bit = dezimal / teiler;

                // Rest ermitteln, der übrig bleibt nach dem der Wert des Bits ermittelt wurde
                rest = dezimal % teiler;

                // dezimal für den nächsten Schleifendurchlauf den Rest der BitErmittlung zuweisen. 
                dezimal = rest;

                //Wenn der Wert von der Variable Bit 1 ist, wird eine 1 ausgegeben
                if (bit == 1)
                { Console.Write("1"); }
                
                //Verhindert eine unnötige vorangestellte 0. Bsp: Statt 0101 wird 101 ausgegeben. 
                else if (i == 0)
                { }

                //Wenn das Bit den Wert 0 hat, wird eine 0 ausgegeben 
                else
                { Console.Write("0"); }

                //Die Variable, die prüft ob eine 0 oder 1 ausgegeben wird
                //muss für den nächsten durchlauf um eine Potenz zurückgestellt werden
                teiler /= 2;

            }
                              
                
 
        }
    }
}
 
Zuletzt bearbeitet:
Jo, das schaut doch schon mal ganz gut aus.

Aber wenn das ganze mal etwas aus dem Üben rausgehen hätte ich noch ein paar Anmerkungen:

- Deine Methode WriteBitCode.
Die ist void und schreibt den Bitcode und noch Text dazu.
Sowas ist prinzipiell eher unschön. Denn stell dir vor du schreibst eine Klasse die du wiederverwenden willst, und da fällt das dann wohl weg.

Am besten ist, wenn solche Objekte nichts direkt irgendwohin schreiben, sondern nur Werte zurückgeben oder Aktionen ausführen.

Also z.B. den Bitcode über eine Eigenschaft (wie in dem Beispiel vorhin) zurückgibt. Für die Ausgabe ist allein die Anwendung zuständig, nicht das jeweilige Objekt.

- Und Fehlermeldungen sollte das Objekt natürlich auch nicht auf die Ausgabe schreiben. Wenn ein unzulässiger Wert eingegeben wurde kannst du den einfach ignorieren (wie in meinem Beispiel). Viel besser ist es natürlich wenn du eine Ausnahme werfen würdest. Die kannst du dann abfangen und daraufhin eine Fehlermeldung ausgeben.
(Wie das geht steht bestimmt irgendwo in deinem Buch. Sorry dazu hab ich immo keine Zeit. Später dann...)
 
Jo, das schaut doch schon mal ganz gut aus.

Aber wenn das ganze mal etwas aus dem Üben rausgehen hätte ich noch ein paar Anmerkungen:

- Deine Methode WriteBitCode.
Die ist void und schreibt den Bitcode und noch Text dazu.
Sowas ist prinzipiell eher unschön. Denn stell dir vor du schreibst eine Klasse die du wiederverwenden willst, und da fällt das dann wohl weg.

Am besten ist, wenn solche Objekte nichts direkt irgendwohin schreiben, sondern nur Werte zurückgeben oder Aktionen ausführen.

Also z.B. den Bitcode über eine Eigenschaft (wie in dem Beispiel vorhin) zurückgibt. Für die Ausgabe ist allein die Anwendung zuständig, nicht das jeweilige Objekt.

- Und Fehlermeldungen sollte das Objekt natürlich auch nicht auf die Ausgabe schreiben. Wenn ein unzulässiger Wert eingegeben wurde kannst du den einfach ignorieren (wie in meinem Beispiel). Viel besser ist es natürlich wenn du eine Ausnahme werfen würdest. Die kannst du dann abfangen und daraufhin eine Fehlermeldung ausgeben.
(Wie das geht steht bestimmt irgendwo in deinem Buch. Sorry dazu hab ich immo keine Zeit. Später dann...)

Ja, zum Teil hat ich die Gedanken auch schon, würde ich nun eine Klasse schreiben die wiederverwenung finden sollte, sollte natürlich besser per return der Bitcode zurückgegeben werden anstatt in der Konsole zu landen.

Zu den fehlermeldungen:

Try Catch und trowexception kram kommt später im Buch (ist mir von java schon ein wenig geläufig), sobald ich da angelangt bin , kann ich den Code ja um diese Fragmente erweitern. Zusätzlich werde ich mich dann noch dran setzen die Klasse so zu ändern, das sie mit einer beliebigen Basis bis ins hexadezimal umgehen kann - zusätzlich die WiriteConsole Befehle rausnehmen und ne separate DLL sraus machen. Dann hab ich jederzeit ne DLL parat falls ich mal ne Klasse zum Umrechnen in andere System brauche :)
 
Zuletzt bearbeitet:
Hey Janchu,
ich hoffe du hast nix dagegen, wenn ich mal kurz deinen Thread hier missbrauche? Hab auch ne kleine VC# Frage:
Ich hab eine 2 Formen (Form1 und TextElement heißen die, ist ja wurst).
In der ersten (Form1) hab ich public ein paar Variablen definiert. Auf die ich aus der 2ten zugreifen will... wie geht das? Ich hatte auf Form1.variable bzw Form1.Methode() gehofft, aber das geht nicht..? (Beide sind im gleichen Namespace)

€: Das geht nicht, bissl nachdenken hilft... ich formulier die Frage mal um: Wie muss ich das alles implementieren, dass ich nen Button drücke, dann ein Fenster aufgeht, wo ich zB nen Text eintragen kann, und dann der Text in eine Variable im Hauptfenster geschrieben wird? Wenn ich ne neue Form mach, die auf den Buttonklick aufgeht, kann ich ja nicht auf die Variablen der alten Form zugreifen...
 
Zuletzt bearbeitet:
€: ch formulier die Frage mal um: Wie muss ich das alles implementieren, dass ich nen Button drücke, dann ein Fenster aufgeht, wo ich zB nen Text eintragen kann, und dann der Text in eine Variable im Hauptfenster geschrieben wird? Wenn ich ne neue Form mach, die auf den Buttonklick aufgeht, kann ich ja nicht auf die Variablen der alten Form zugreifen...

Um einen Wert an ein neues Form zu übergeben ist es möglich, zu dem normalen (leeren) Default Constructor einen weiteren Contructor zu erstellen, um diesen Parameter zu übergeben.


Code:
public class NewForm
{
 private string _myVar;
 public string MyVar
 {
   get { return _myVar; }
   set { _myVar = value; }
 }

 //Default Constructor
 public NewForm()
 {
 }

 //Zusätzlicher constructor fuer Parameterübergabe
 public NewForm(string var)
 {
   this._myVar = var;
 }

 //Event, um den Text aus einem TextBox field auszulesen
 private void OnButtonClick (object sender , EventArgs e)
 { 
  if(!string.IsNullOrEmpty(this.txtBox.text)
  {
   this.DialogResult = DialogResult.OK;
   this._myVar = this.txtBox.Text;
   this.Close();
  }
 }
}

Im Hauptform wird das neue Form dann wie folgt aufgerufen:
NewForm dlg = new NewForm("someValue");
dlg.Show();

Da die variable "myVar" public "Getter" und "Setter" hat, kann man diese variable z.B. auch auslesen

NewForm dlg = new NewForm();
if(dlg.Show() == DialogResult.OK)
{
string var = dlg.MyVar;
}
 
Klaro, mit Konstruktoren geht der eine Weg :wall: die Idee hätte ich auch haben können...
Aber das Problem ist: Ich schreib zu Testzwecken eine doppelt verkette Liste, da gibts natürlich ein Start und ein Ende Element, der Rest ist zwischendrin eingehängt. Die Klasse "Liste" von mir ist halt einfach unter der Form1 in den Quelltext geschrieben.
Ich möchte jetzt eine neue Form2, wo ich ein neues Element erzeugen kann.
Damit muss ich aber zum einen auf die Klasse Liste zugreifen, zum andren auf "Form1.start" und "Form1.ende" um die Liste zu modifizieren...

Das mit der "Liste" ist kein Thema, da mach ich ne extra Klasse draus, und alss beide die benutzen, dann sollte das schonmal gehn.

Aber wie kann ich in der Form2 die start/ende-Variablen von der Form1 manipulieren?
 
Warum willst Du direkt aus einem anderen Form auf diese Liste zugreifen und nicht einfach nur über den Dialog einen neuen Wert beziehen?

Code:
using System.Collections;

MainClass
{
 private List<string> _myList;
 
 public MainClass()
 {
  this._myList = new List<string>();
 }
 
 private void OnButtonClick (object sender , EventArgs e)
 { 
  NewForm dlg = new NewForm();
  if(dlg.Show() == DialogResult.OK)
  {
    if(!string.IsNullOrEmpty(dlg.MyVar)
    {
     this._myList.Add(dlg.MyVar);
    }
  }
 }
}

Um direkt auf das Hauptform zuzugreifen:

Code:
public class NewForm
{
 private MainForm _mainForm;
 private string _myVar;
 public string MyVar
 {
   get { return _myVar; }
   set { _myVar = value; }
 }

 //Default Constructor
 public NewForm()
 {
  //Möglichkeit1
  //this._mainForm = (MainForm) this.Parent;
 }

 //Zusätzlicher constructor mit dem parent als parameter
 public NewForm(MainForm mainForm)
 {
   this._mainForm = mainForm;
 }

 //Event, um den Text aus einem TextBox field auszulesen
 private void OnButtonClick (object sender , EventArgs e)
 { 
  if(!string.IsNullOrEmpty(this.txtBox.text)
  {
   this.DialogResult = DialogResult.OK;
   this._mainForm.PublicVarValue = this.txtBox.Text;
   this.Close();
  }
 }
}

Diese Vorgehensweise ist allerdings nicht sehr sauber und du kannst ThreadUI Probleme bekommen. Sauberer wäre ein neuer Event im MainForm um die Liste zu ändern.
 
Hardwareluxx setzt keine externen Werbe- und Tracking-Cookies ein. Auf unserer Webseite finden Sie nur noch Cookies nach berechtigtem Interesse (Art. 6 Abs. 1 Satz 1 lit. f DSGVO) oder eigene funktionelle Cookies. Durch die Nutzung unserer Webseite erklären Sie sich damit einverstanden, dass wir diese Cookies setzen. Mehr Informationen und Möglichkeiten zur Einstellung unserer Cookies finden Sie in unserer Datenschutzerklärung.


Zurück
Oben Unten refresh