Zum Inhalt springen

Eigene Klasse in VB.net umschreiben für C#


Empfohlene Beiträge

Geschrieben

Vielen Dank noch mal an alle

Es geht auch so etwas:

 public class ResultWriter
    {     
        virtual public void SendToFile(ICalculation calculation)
        {
            using (System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\VB_net\\Test.txt", true))
            {
                sw.WriteLine(calculation.Calculate());
            }
        }
    }

Aber die anderen Varianten sind sehr interessant.

Gruß

Eleu

 

Geschrieben

File.AppendAllText() macht im Grunde nichts anderes, was du geschrieben hast:

public static void AppendAllText(String path, String contents)
{
    // ...
    InternalAppendAllText(path, contents, StreamWriter.UTF8NoBOM);
}

private static void InternalAppendAllText(String path, String contents, Encoding encoding)
{
    // ...
    using (StreamWriter sw = new StreamWriter(path, true, encoding))
        sw.Write(contents);
}

So sieht der Source Code im .NET Framework aus.

Geschrieben
vor 39 Minuten schrieb Whiz-zarD:

File.AppendAllText() macht im Grunde nichts anderes, was du geschrieben hast:


public static void AppendAllText(String path, String contents)
{
    // ...
    InternalAppendAllText(path, contents, StreamWriter.UTF8NoBOM);
}

private static void InternalAppendAllText(String path, String contents, Encoding encoding)
{
    // ...
    using (StreamWriter sw = new StreamWriter(path, true, encoding))
        sw.Write(contents);
}

So sieht der Source Code im .NET Framework aus.

System.IO.File liefert mir aber keine Methode, um zeilenweise in die Datei zu schreiben. Es fehlt die Methode WriteLine.

Oder was müsste ich ändern, damit zeilenweise hineingeschrieben wird?

 File.AppendAllText(_file, $"{calculation.GetType()} result: {calculation.Calculate()}");

 

Geschrieben (bearbeitet)

Könntest ein Environment.NewLine hinten dranhängen Wenn du bei File bleiben möchtest:

 File.AppendAllText(_file, $"{calculation.GetType()} result: {calculation.Calculate()}{Environment.NewLine}");

Dann wird am Ende der Zeile ein Zeilenumbruch eingefügt.

Bearbeitet von r4phi
Geschrieben
vor 4 Minuten schrieb r4phi:

Könntest ein Environment.NewLine hinten dranhängen Wenn du bei File bleiben möchtest:


 File.AppendAllText(_file, $"{calculation.GetType()} result: {calculation.Calculate()}{Environment.NewLine}");

Dann wird am Ende der Zeile ein Zeilenumbruch eingefügt.

Ich denke, da muss ich mir noch so einiges anschauen ;)

Geschrieben
vor 3 Minuten schrieb Eleu:

Ich denke, da muss ich mir noch so einiges anschauen ;)

Environment.NewLine macht eigentlich nichts spannendes.
Abhängig vom Betriebssystem bzw. der Plattform liefert es dir die Zeichen für einen Zeilenumbruch zurück.

Bei Windows wäre das bspw. "\n\r"

Geschrieben (bearbeitet)

Dass der Text nicht superschön ist, stimmt. Du könntest dir jetzt überlegen, ob du in deinem ICalculation Interface noch eine Methode definierst, die eine "schöne" Ausgabe liefert. Beispielsweise:

public interface ICalculation
{
 double Calculate();
  string GetRepresentation();
}

public abstract class BinaryCalculation : ICalculation
{
 // ... bekannter Kram
  public abstract string GetRepresentation();
}

public class Addition : BinaryCalculation
{
 // ... bekannter Kram
  public string GetRepresentation()
  {
   return $"Addition: ({_firstOperand} + {_secondOperand})"; 
  }
}

//... beim Schreiben:
File.AppendAllText(_file, $"{calculation.GetRepresentation()}, result: {calculation.Calculate()}");

Damit bekämst du dann eine vernünftig lesbare Ausgabe à la "Addition: (5 + 4), result: 9".

 

p.s. Das ganze kann man auch durch überschreiben von ToString erreichen, ich finde das explizit aber manchmal angenehmer.

Bearbeitet von arlegermi
Geschrieben (bearbeitet)

Hallo arlegermie,

vielen dank ich probiere das mal aus.

Ich hoffe ich nerve nicht, denn ich hätte noch ein paar Fragen, bzgl. der prinzipiellen Vorgehensweise, bei der Klassenprogrammierung mit Vererbung.

Ich habe jetzt folgende Klassen und ein Interface programmiert:

{
    public interface ICalculation
    {
        double Calculate();
    }

    public abstract class BinaryCalculation : ICalculation
    {
        protected double _firstOperand;
        protected double _secondOperand;
        public BinaryCalculation(double a, double b)
        {
            _firstOperand = a;
            _secondOperand = b;
        }

        public abstract double Calculate();
    }

    public class Addition : BinaryCalculation
    {
        public Addition(double a, double b) : base(a, b) { }

        public override double Calculate() => _firstOperand + _secondOperand;
    }

    public class Multiplikation : BinaryCalculation
    {
        public Multiplikation(double a, double b) : base(a, b) { }

        public override double Calculate() => _firstOperand * _secondOperand;
    }

    public class ResultWriter
    {
        private string _file;

        public ResultWriter(string path)
        {
            _file = path; // Dateipfad und Dateiname werden der Variablen _file übergeben
        }

        public void WriteResultToFile(ICalculation calculation) //Vereerbung über das Interface ICalculation
        {
            File.AppendAllText(_file, $"{calculation.GetType()} result: {calculation.Calculate()}{Environment.NewLine}");
        }
    }
}

Nun möchte ich eine Klasse programmieren, die 3 Variable addieren soll. Wenn ich es nun richtig verstanden habe, müsste ich nun eine neue Klasse Addieren2 programmieren, mit einer Methode Calculate2, sowie ein weitere abstrakte Klasse BinaryCalculation2, um nicht gegen das  Single-Responsibility-Prinzip zu verstoßen. Soll ich dann im Interface ICalculation diese Methode Calculate2 einfügen, oder soll ich ein neues Interface ICalculation2 hinzufügen?  

Oder kann ich die Calculate auch für Addition2 verwenden?

Sahe dann so aus:

    public abstract class BinaryCalculation2 : ICalculation
    {
        protected double _firstOperand;
        protected double _secondOperand;
		protectet double _thirdOperand;

        public BinaryCalculation2(double a, double b, double c)
        {
            _firstOperand = a;
            _secondOperand = b;
			_thirdOperand = c;
        }

        public abstract double Calculate();
    }

    public class Addition2 : BinaryCalculation2
    {
        public Addition(double a, double b, double c) : base(a, b, c) { }

        public override double Calculate() => _firstOperand + _secondOperand + _thirdOperand;
    }

Ist das die richtige Vorgehensweise?

Edit: Letztgenannte Variante funktioniert jedenfalls.

Bearbeitet von Eleu
Geschrieben

 

vor 3 Minuten schrieb Eleu:

Nun möchte ich eine Klasse programmieren, die 3 Variable addieren soll. Wenn ich es nun richtig verstanden habe, müsste ich nun eine neue Klasse Addieren2 programmieren, mit einer Methode Calculate2, sowie ein weitere abstrakte Klasse BinaryCalculation2, um nicht gegen das  Single-Responsibility-Prinzip zu verstoßen.

Im Grunde haben wir schon alles, was wir brauchen. ;)
Wir haben doch das Interface ICalculation, dessen Methode Calculate() ein double zurückgibt, also ein Parameter für die Addition-Klasse.
Wenn du drei Zahlen miteinander addieren möchtest, kannst du es ganz einfach machen:

new Addition(new Addition(1,2).Calculate(), 3)

Jetzt rechnet er 1 + 2 + 3.

Geschrieben (bearbeitet)

Du könntest jetzt einfach eine Methode schreiben die einen String mit Operatoren übergibt "+-*\\" und ein Array mit den Operanden. Du müsstest nur überprüfen ob das Array.Length gleich string.Length + 1 ist, damit die Rechnung funktioniert.

Dann könntest du die chars den Strings auslesen und jeweils die Methode (Addition usw) ausführen. Wobei man dann erst nach Multiplikationen und Divisionen suchen müsste. Ebenfalls müsste man die Division durch 0 abfangen.

Das ist natürlich nur nützlich, wenn du längere Rechnungen angeben willst, anstatt schrittweise Ergebnisse anzugeben.

Es gab mal so eine Standardlösung, die Eingabe sah dann so aus  "+-/*54123", die aber (in meiner Erinnerung) nur für die Zahlen von 0-9 funktionierte. Mir fällt nur nicht mehr der Name ein...

Kannst noch viel machen :). Diese Rechner werden meist unterschätzt.

 

Bearbeitet von KeeperOfCoffee
Geschrieben (bearbeitet)
vor 28 Minuten schrieb KeeperOfCoffee:

...

:blink:

Ich glaube, es wird echt mal Zeit, dass ich mein Artikel "Wie man einen Taschenrechner programmiert" veröffentliche.

vor 28 Minuten schrieb KeeperOfCoffee:

Es gab mal so eine Standardlösung, die Eingabe sah dann so aus  "+-/*54123", die aber (in meiner Erinnerung) nur für die Zahlen von 0-9 funktionierte. Mir fällt nur nicht mehr der Name ein...

Du meinst wohl die (umgekehrte) polnische Notation. Genannt auch Postfix- und Präfix-Schreibweise.
Eine Umwandlung von der bekannten Infix-Schreibweise in die Post-/Präfix-Schreibweise, lässt sich durch den Shunting-Yard-Algorithmus lösen. Das würde hier aber viel zu weit gehen.

Bearbeitet von Whiz-zarD
Geschrieben
vor einer Stunde schrieb Whiz-zarD:

 

Im Grunde haben wir schon alles, was wir brauchen. ;)
Wir haben doch das Interface ICalculation, dessen Methode Calculate() ein double zurückgibt, also ein Parameter für die Addition-Klasse.
Wenn du drei Zahlen miteinander addieren möchtest, kannst du es ganz einfach machen:


new Addition(new Addition(1,2).Calculate(), 3)

Jetzt rechnet er 1 + 2 + 3.

Es funktioniert, aber ich habe noch nicht ganz kapiert wie das gehen kann?

Was müsste ich denn programmieren, wenn ich noch eine weitere 4te Zahl addieren möchte? 

Geschrieben
vor 10 Minuten schrieb Eleu:

Was müsste ich denn programmieren, wenn ich noch eine weitere 4te Zahl addieren möchte? 


Um mit vier Zahlen zu rechnen:

new Addition(new Addition(new Addition(1,2).Calculate(), 3).Calculate(), 4)
Zitat

Es funktioniert, aber ich habe noch nicht ganz kapiert wie das gehen kann?

Eigentlich ganz einfach

new Addition(1,2).Calculate() => liefert Ergebnis X.
Ergebnis X packst du wiederum als ersten Summanden in deine Addition Klasse.
Wenn man das ganze nicht einzeilig machen möchte würde das so aussehen:

var x = new Addition(1,2).Calculate();
var result = new Addition(x, 3).Calculate();

Und bei vier Zahlen:

var x = new Addition(1, 2).Calculate();
var y = new Addition(x, 3).Calculate();
var result = new Addition(y, 4).Calculate();

 

Geschrieben
vor 12 Minuten schrieb Whiz-zarD:

:blink:

Ich glaube, es wird echt mal Zeit, dass ich mein Artikel "Wie man einen Taschenrechner programmiert" veröffentliche.

Macht man natürlich anders. Trotzdem sollte er, wenn er z.B. 1000 Additionen hat, die Rechnung doch besser auslesen und entsprechend auswerten.

Es ist ein Unterschied, ob es immer x (operator) y macht, oder eine fertige Rechnung eingibt (sich zusammenklickt) und das Ergebnis haben will. Der Windows Rechner rechnet auch stupid eine Operation nach der anderen aus und zeigt am Ende an: 6+6*2 = 24 ;) was so natürlich nicht stimmt, aber die Aufbau des Rechners macht es nunmal so.

vor 8 Minuten schrieb Eleu:

s funktioniert, aber ich habe noch nicht ganz kapiert wie das gehen kann?

Was müsste ich denn programmieren, wenn ich noch eine weitere 4te Zahl addieren möchte? 

Das müsste dann sein

new Addition(new Addition(new Addition(1,2).Calculate(), 3).Calculate(),  4)

 

Geschrieben (bearbeitet)

Vielleicht führt das jetzt zu weit (und wirklich sinnvoll ist es außer als Übung auch nicht), aber:

Anstatt die BinaryCalculations ineinander zu schachteln kannst du dir auch überlegen, eine Klasse zu schreiben, die beliebig viele Operanden akzeptiert und die dann alle aufaddiert. Das Gerüst könnte so aussehen:

public class SeriesCalculation : ICalculation
{
  private BinaryCalculation _binaryCalculation;
  private double[] _numbers;
  
 public SeriesCalculation(BinaryCalculation binaryCalculation, params double[] numbers)
 {
   _binaryCalculation = binaryCalculation;
   _numbers = numbers;
 }
  
  public double Calculate()
  {
   // immer zwei Zahlen aus _numbers nehmen, die Berechnung ausführen und das Ergebnis in die
   // nächste Berechnung übergeben.
  }
}

//aufrufbar wäre das dann folgendermaßen:
var calc = new SeriesCalculation(new Addition(), 1,2,3,4,5,6); // hierfür bräuchtest du noch einen neuen Konstruktor in Addition

Wie gesagt: Das mag gerade ein wenig zu kompliziert sein, ist vielleicht aber eine ganz schöne Übung, um das Prinzip zu verstehen. Einfacher ist's vielleicht erstmal immer nur aufzuaddieren, ohne die Berechnung auch von außen mit reinzunehmen.

Wenn "params" neu für dich ist, kannst du hier was dazu lesen.

Bearbeitet von arlegermi
Geschrieben
vor 2 Minuten schrieb KeeperOfCoffee:

Der Windows Rechner rechnet auch stupid eine Operation nach der anderen aus und zeigt am Ende an: 6+6*2 = 24 ;) was so natürlich nicht stimmt, aber die Aufbau des Rechners macht es nunmal so.

Das stimmt nicht ganz. Stellt man den Taschenrechner auf "Wissenschaftlich", so kennt er auch eine Operatorreihenfolge.

Geschrieben
vor 1 Minute schrieb arlegermi:

Genau, da geht's quasi hin. Auch wenn man das "in echt" natürlich anders lösen würde.

Wobei, das SeriesCalculation wäre im der "Context" und "BinaryCalculation" wäre die "Strategy" die du den Context injectest.

Geschrieben (bearbeitet)

Hallo,

ich kann euch jetzt nicht mehr so ganz folgen, aber das ist nicht so schlimm.  Ich schau mir das noch mal in Ruhe an. 

Interessant finde ich jedenfalls, dass ich damit  auch meine Multiplikations-Klasse mit der Additions-Klasse verketten kann: 

private void button5_Click(object sender, EventArgs e)
 {
  Addition s = new Addition(new Multiplikation(new Addition(1, 2).Calculate(), 13).Calculate(), 4);
  MessageBox.Show(Convert.ToString(s.Calculate()))
 }

Die Message Box zeigt mir 43 als Ergebnis  an

Bearbeitet von Eleu
Geschrieben
vor 10 Minuten schrieb Eleu:

Interessant finde ich jedenfalls, dass ich damit  auch meine Multiplikations-Klasse mit der Additions-Klasse verketten kann: 

Bitte nicht durcheinander kommen.
Du verkettest die Ergebnisse (Rückgabewerte) der Calculate Methode!

Geschrieben
vor 15 Minuten schrieb r4phi:

Bitte nicht durcheinander kommen.
Du verkettest die Ergebnisse (Rückgabewerte) der Calculate Methode!

  private void button6_Click(object sender, EventArgs e)
        {
        double x = new Addition(1, 2).Calculate();
        double y = new Multiplikation(x, 13).Calculate();
        double result = new Addition(y, 4).Calculate();
        MessageBox.Show(Convert.ToString(result));
        }

Ja, mit deinem Beispiel ist es für mich verständlicher..

Geschrieben (bearbeitet)
vor 14 Minuten schrieb Eleu:

Ja, mit deinem Beispiel ist es für mich verständlicher..

Mal langsam. 1+2*13+4

wäre ja dann.

double x = new Multiplikation(2, 13).Calculate();

double y = new Addition(new Addition(x, 1).Calculate(), 4).Calculate();

// y = 31

Die Frage ist also genau, wo du deine Multiplikation in der Rechnung haben willst.

Desweiteren solltest du das nicht in das Klick Ereignis des Buttons packen.

Bearbeitet von KeeperOfCoffee

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.


Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...