Entwickler-Ecke
Sonstiges (.NET) - Kleine Aufgabe: explizite Typumwandlung - Währungsumrechnung
derprogrammier69 - Do 30.01.14 17:10
Titel: Kleine Aufgabe: explizite Typumwandlung - Währungsumrechnung
Hi meine Freunde,
ich habe eine Aufgabe zu bewältigen, bei der ich iwie keinen Ansatz finde.
Bräuchte nur einen kleinen Einstiegstipp.
Die Aufgabe lautet:
•Implementieren Sie explizite Cast-Operatoren, so dass eine Währungsumwandlung zwischen den Klassen mittels expliziterCastsmöglich ist. Bei einem Cast zwischen den Währungen, soll der entsprechende Umrechnungsfaktor verwendet werden.
Das Grundgerüst habe ich schon implementiert, über explizite/implizite Typecasts weiss ich bescheid:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| namespace ConsoleApplication3 { public class BaseCurrency { public double Value; public CurrencyEnum Currency; }
public enum CurrencyEnum { Dollar, Yen, Euro, Pound }
public class Dollar : BaseCurrency { }
public class Yen : BaseCurrency { }
public class Euro : BaseCurrency { }
public class Pound : BaseCurrency { }
public class Program { static void Main(string[] args) { } } } |
*P.S. Wie fügt man eigtl. den Code als Code ein, ich möchte euch nicht jedes Mal die Mehrarbeit machen, dass ein Moderator meinen Post ändern muss?
MFG
Moderiert von
Christian S.: C#-Tags hinzugefügt
Ralf Jansen - Do 30.01.14 17:16
Zitat: |
über explizite/implizite Typecasts weiss ich bescheid: |
Warum fragst du dann wenn du schon Bescheid weißt :gruebel: Oder hab ich die eigentliche Frage verpasst?
Code in
[cs]deinCode[/cs] Tags setzen, Code markieren und ALT+R klicken oder einfach die Menüs im Editor verwenden. ToolBar Bereiche Sprache in der ComboBox auswählen, Code markieren und das + neben der ComboBox klicken.
Ralf Jansen - Do 30.01.14 18:16
Das sollen wir mal festhalten ;) Es ist ein Aufgabe die wohl ein bestimmtes Sprachfeature nutzen und damit erklären soll. Die Aufgabe selbst würde man in Realität aber nie nimmer nicht so lösen.
Ist wohl irgendein Lehrerdefizit. Man nehme immer Bespiele die keinerlei Praxisrelevanz haben.
Palladin007 - Do 30.01.14 20:06
Ich würde auch die ganzen erbenden Klassen weg lassen und im Hintergrund ein Mapping zwischen den Währungen mit der jeweiligen Umrechnungszahl anlegen, oder mir irgendetwas anderes ausdenken, aber wahrscheinlich hast du wirklich Recht :D
derprogrammier69 - Do 30.01.14 20:09
-> das hört sich doch gut an, probiere es morgen aus. ist halt eine aufgabe von meinem uni-prof (wie schon vermutet) danke, mfg
derprogrammier69 - Fr 31.01.14 16:51
hi, habe es hinbekommen :)
eine frage habe ich noch, die ich mir eigtl. schon selbst beantwortet (logik) hab, die ich aber trotzdem nochmal abgesichert haben möchte: man kann nicht implizite UND explizite typecasts zusammen in eine klasse schreiben, also das geht nicht, oder?:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| public class Dollar : BaseCurrency { public Dollar(double temp) { this.Value = temp; this.Currency = CurrencyEnum.Dollar; }
public static explicit operator Euro(Dollar dollar) { return new Euro(dollar.Value / 1.3512); }
public static implicit operator Euro(Dollar dollar) { return new Euro(dollar.Value / 1.3512); } } |
hier die korrekte lösung von meiner ersten frage. habe mal nur euro->dollar und dollar->euro implementiert.:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61:
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace ConsoleApplication3 { public class BaseCurrency { public double Value; public CurrencyEnum Currency; }
public enum CurrencyEnum { Dollar, Euro }
public class Dollar : BaseCurrency { public Dollar(double temp) { this.Value = temp; this.Currency = CurrencyEnum.Dollar; }
public static explicit operator Euro(Dollar dollar) { return new Euro(dollar.Value / 1.3512); } }
public class Euro : BaseCurrency { public Euro(double temp) { this.Value = temp; this.Currency = CurrencyEnum.Euro; }
public static explicit operator Dollar(Euro euro) { return new Dollar(1.3512 * euro.Value); } }
public class Program { static void Main(string[] args) { Euro eurobetrag = new Euro(20); Dollar dollarbetrag = (Dollar)eurobetrag; Console.WriteLine("{0}{1}",dollarbetrag.Value, dollarbetrag.Currency); } } } |
Ralf Jansen - Fr 31.01.14 17:00
Zitat: |
man kann nicht implizite UND explizite typecasts zusammen in ein klasse |
Hast du doch? Wenn du meinst in einer Methode dann nein. Vergiss das. Ich sollte besser lesen :( Explicit ist nur Explicit. Implicit ist beides. Wenn du implicit implementierst kannst du dann auch explicit.
Der Enum ist vollkomen überflüssig du unterscheidest die Klassen durch ihren Typ. Im Moment ist es sogar noch gefährlich jemand könnte sich einen Dollar erzeugen und Currency trotzdem auf Euro setzen.
Also entweder du benutzt einen Enum ODER Ableitung aber nicht beides.
derprogrammier69 - Fr 31.01.14 17:12
vielen dank für die antwort. das mit dem enum in kombination mit den ableitungen war wieder GENAUSO in der aufgabenstellung vorgeschrieben (uni), verstehe aber deinen einwand. mfg
Palladin007 - Fr 31.01.14 21:15
Also einfach nur um diese (meiner Meinung nach) sehr dämliche Aufgabe etwas sinnvoller auf zu rollen:
C#-Quelltext
1: 2: 3: 4: 5:
| public enum CurrencyEnum { Dollar, Euro } |
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| public static class CurrencyConversionFactorMapping { private readonly static IDictionary<Tuple<CurrencyEnum, CurrencyEnum>, decimal> _conversionFactorMapping;
static CurrencyConversionFactorMapping() { _conversionFactorMapping = new Dictionary<Tuple<CurrencyEnum, CurrencyEnum>, decimal>();
_conversionFactorMapping.Add(Tuple.Create(CurrencyEnum.Dollar, CurrencyEnum.Euro), 1m / 1.36111m); _conversionFactorMapping.Add(Tuple.Create(CurrencyEnum.Euro, CurrencyEnum.Dollar), 1.36111m); }
public static decimal GetFactor(CurrencyEnum sourceCurrency, CurrencyEnum targetCurrency) { decimal result = -1;
var tupelKey = Tuple.Create(sourceCurrency, targetCurrency);
if (sourceCurrency == targetCurrency) result = 1m; else if (_conversionFactorMapping.ContainsKey(tupelKey)) result = _conversionFactorMapping[tupelKey]; else throw new NotSupportedException();
return result; } } |
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| public class BaseCurrency { public static implicit operator decimal(BaseCurrency currency) { return currency.Value; }
public decimal Value { get; private set; } public CurrencyEnum Currency { get; private set; }
public BaseCurrency(decimal value, CurrencyEnum currency) { Value = value; Currency = currency; }
public BaseCurrency CalculateTo(CurrencyEnum targetCurrency) { var factor = CurrencyConversionFactorMapping.GetFactor(this.Currency, targetCurrency);
return new BaseCurrency(this.Value * factor, targetCurrency); } } |
Optimal ist diese Lösung auch nicht, aber definitiv besser, finde ich.
Einen Operator hast du auch drin, da wäre er sogar sinnvoller.
Gruß
derprogrammier69 - Sa 01.02.14 17:13
Palladin007 hat folgendes geschrieben : |
Also einfach nur um diese (meiner Meinung nach) sehr dämliche Aufgabe etwas sinnvoller auf zu rollen:...
|
hi, ;) ziel war es einfach nur in einem bsp. mal implizite/explizite typen einzuüben, mir hat es geholfen, hab die syntax jetzt verinnerlicht.
die letzte teilaufgabe wirft nun jedoch erneut fragezeichen in meinem kopf auf:
•Implementieren Sie auch Operatorüberladungen, um einzelne Objekte addieren und subtrahieren zu können, z.B. in der Form:
MyDollar= MyYen+ MyEuro;
meine lösung klappt iwie nicht (bin davon ausgegangen, dass ich durch eingabeparameter=dollar egal welche währung addieren kann und sie implizit in dollar umgewandelt wird):
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| public static Dollar operator +(Dollar waehrung1, Dollar waehrung2) { return new Dollar(waehrung1.Value + waehrung2.Value); }
MAIN-Methode: Euro e = new Euro(20); Yen y = new Yen(100); Dollar d = e + y; Console.WriteLine(d); |
habe nun im quellcode noch den yen-code diesbzgl. ergänzt:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90:
| namespace ConsoleApplication3 { public class BaseCurrency { public double Value; public CurrencyEnum Currency; }
public enum CurrencyEnum { Dollar, Euro, Yen }
public class Dollar : BaseCurrency { public Dollar(double temp) { this.Value = temp; this.Currency = CurrencyEnum.Dollar; }
public static implicit operator Euro(Dollar dollar) { return new Euro(dollar.Value * 0.741); }
public static implicit operator Yen(Dollar dollar) { return new Yen(102.345 * dollar.Value); } }
public class Euro : BaseCurrency { public Euro(double temp) { this.Value = temp; this.Currency = CurrencyEnum.Euro; }
public static implicit operator Dollar(Euro euro) { return new Dollar(1.3512 * euro.Value); }
public static implicit operator Yen(Euro euro) { return new Yen(138.028 * euro.Value); } }
public class Yen : BaseCurrency { public Yen(double temp) { this.Value = temp; this.Currency = CurrencyEnum.Yen; }
public static implicit operator Dollar(Yen yen) { return new Dollar(0.0097 * yen.Value); }
public static implicit operator Euro(Yen yen) { return new Dollar(0.0072 * yen.Value); } }
public class Program { static void Main(string[] args) { Euro eurobetrag = new Euro(20); Dollar dollarbetrag = eurobetrag; Yen yenbetrag = eurobetrag; Console.WriteLine("{0}{1} sind...", eurobetrag.Value, eurobetrag.Currency); Console.WriteLine("{0}{1}",dollarbetrag.Value, dollarbetrag.Currency); Console.WriteLine("{0}{1}", yenbetrag.Value, yenbetrag.Currency);
} } } |
vielen dank für schnelle und kompetente hilfe (am besten schon code ;) ). mfg
Ralf Jansen - Sa 01.02.14 17:33
Du traust dem Compiler zuviel Intelligenz zu ;)
Der Ausdruck e + y wird ausgewertet unabhängig davon das er später einem Dollar zugewiesen wird. Das ist Prinzipiell so bei diesen rechter Ausdruck linker Ausdruck Geschichten. Und wenn du nur e + y betrachtest kann der Compiler nicht erahnen das es sinnvoll ist die eigentlich unabhängige Klasse Dollar zu verwenden und sowohl e als auch y dahin zu casten.
Anderes äquivalentes Beispiel
7 und 5 sind Integer als wird eine Integer Division erfolgen die den Integer 1 ergibt und dann wird auf double gecastet. x wird also 1 sein und nicht die potentiell erhofften 1,4.
Also immer schön die Auswertereihenfolge beachten.
Über das eigentliche Problem denke ich nochmal kurz nach vielleicht fällt mir was halbwegs sinnvolles ein das die Operatorüberladung verwendet ohne alle möglichen Typkombinationen implementieren zu müssen. Dummerweise geht die gesamte Operatorüberladung in .Net nicht mit generischen Typen.
derprogrammier69 - Sa 01.02.14 17:37
hi, ich muss keine generische implementierung, die jeden einzelfall abdeckt, programmieren (wäre nett zu wissen, muss aber echt nicht sein).
mir reicht es (und das muss ich eh 100% für die klausur wissen), wenn ich das ersma mit myDollar=myYen+myEuro hinbekomme...
habe eine weitere lösung implementiert, die iwie auch nicht funkioniert :( :
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| IN DOLLAR-KLASSE: public static Dollar operator +(Yen y, Euro e) { Dollar yenumwandl = y; Dollar euroumwandl = e; return new Dollar(yenumwandl.Value + euroumwandl.Value); }
MAIN-Methode: Yen y = new Yen(100); Euro e = new Euro(20); Dollar d = y + e; |
Fehler: Der Operator "+" kann nicht auf Operanden vom Typ ...Yen und ...Euro angewandt werden.
p.s. eigtl. unterschätze ich immer den compiler ;)
Ralf Jansen - Sa 01.02.14 17:57
Wenn du + Dollar überlädst muss einer der beiden beteiligten Operanden auch Dollar sein.
Sonst könntest du ja genau diese Parameter Kombination in allen ~Currency~ Klassen Implementieren. Woher sollte der Compiler dann wissen welche er nehmen soll. Das wäre also völlig uneindeutig.
Stell dir folgendes vor
C#-Quelltext
1:
| BaseCurrency x = yen + euro; |
Wenn Yen + Euro in allen Klassen implemetiert wäre welche sollte gewählt werden?
Ich würde dir empfehlen etwas in der Richtung
C#-Quelltext
1: 2: 3: 4:
| public static Yen operator +(Yen yen, BaseCurrency currency) { return new Yen(yen.Value + ((Yen)currency).Value); } |
zu versuchen. Das hält zumindest die Anzahl der nötigen Implementierungen etwas in Grenzen.
Für dein Beispiel
würde obige Beispielmethode in Yen ziehen. Die Konvertierung nach Dollar passiert dann danach implicit bei der Zuweisung. Ob das casten von der konkreten Basecurrency nach Yen in der Methode so funktioniert kann ich grad nicht ausprobieren :(
Ralf Jansen - Sa 01.02.14 18:44
Zitat: |
Ob das casten von der konkreten Basecurrency nach Yen in der Methode so funktioniert kann ich grad nicht ausprobieren :( |
Ok, geht nicht :( Man müßte erst auf den konkreten Typ casten und dann auf den konkreten Typ.
Im Moment fällt mir nichts besseres ein als Kombinatorik und in jeder Klasse für jeden möglichen 2.ten Operator + zu überladen.
derprogrammier69 - So 02.02.14 01:43
Ralf Jansen hat folgendes geschrieben : |
Zitat: | Ob das casten von der konkreten Basecurrency nach Yen in der Methode so funktioniert kann ich grad nicht ausprobieren :( |
Ok, geht nicht :( Man müßte erst auf den konkreten Typ casten und dann auf den konkreten Typ.
Im Moment fällt mir nichts besseres ein als Kombinatorik und in jeder Klasse für jeden möglichen 2.ten Operator + zu überladen. |
BITTE UM KOMPETENTE HILFE :) DANKE
so schwer kann dollar = yen + euro doch nicht sein, lösung der aufgabe weiterhin zur fahndung ausgeschrieben :D!
derprogrammier69 - Mo 03.02.14 19:34
LETZTEMA PUSH:
bitte bitte helft mir :)
Ralf Jansen - Mo 03.02.14 20:27
So wie ich es weiter oben beschrieben habe. Nur das du eben nicht so wie gehofft hatte BaseCurrency übergeben kannst sondern einen konkrete Ableitung nehmen mußt. Z.B. Euro
derprogrammier69 - Mi 05.02.14 14:16
hi, achso habe das nicht herausgelesen :) hab mich schon gewundert, dass du nicht mehr geantwortet hast.
abschliessend habe ich dennoch ein kleines rätsel zu lösen, dass ich selber nicht herausbekomme, obwohl ich schon alles probiert habe (aufmalen,...).
hier erstmal der code auf den ich mich beziehe:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| EURO-Klasse: public static Euro operator +(Euro e, Yen y) { Euro yenINeuro = y; return new Euro(e.Value + yenINeuro.Value); }
MAIN-Methode: Yen y = new Yen(2026); Euro e = new Euro(14.8); Dollar d = e + y;
Console.WriteLine("-------------------"); Console.WriteLine("{0}{1}",d.Value, d.Currency); |
ich möchte nun wie in der main-methode schon deklariert Dollar d = e + y rechnen.
das ergebnis soll 40Dollar lauten, da 2026Yen UND 14.8Euro jew. ca. 20Dollar sind.
wenn man in der operator-überladung einfach nur "return new Euro(e.Value + yen.Value);" würde ja folgendes geschehen: "return new Euro(14.8 + 2026);" und später bei der addition würden dann 2040.8Euro in Dollar umgewandelt (möchte ich ja nicht - s.o.)
-> DESWEGEN muss ich iwie vorher Yen y in Euro umwandeln, dass habe ich durch den zwischenschritt "Euro yenINeuro = y;" erreichen wollen, LEIDER erscheint nun die gewünschte von ca. 40Dollar NICHT (sondern ca. 34.6Dollar)
-> der zugrunde liegende fehler bleibt mir schleierhaft, habe echt alles durchdacht meiner meinung nach
hier nochmal der ganze code:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116:
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace ConsoleApplication3 { public class BaseCurrency { public double Value; public CurrencyEnum Currency; }
public enum CurrencyEnum { Dollar, Euro, Yen }
public class Dollar : BaseCurrency { public Dollar(double temp) { this.Value = temp; this.Currency = CurrencyEnum.Dollar; }
public static implicit operator Euro(Dollar dollar) { return new Euro(dollar.Value * 0.741); }
public static implicit operator Yen(Dollar dollar) { return new Yen(102.345 * dollar.Value); } }
public class Euro : BaseCurrency { public Euro(double temp) { this.Value = temp; this.Currency = CurrencyEnum.Euro; }
public static implicit operator Dollar(Euro euro) { return new Dollar(1.3512 * euro.Value); }
public static implicit operator Yen(Euro euro) { return new Yen(138.028 * euro.Value); }
public static Euro operator +(Euro e, Yen y) { Euro yenINeuro = y; return new Euro(e.Value + yenINeuro.Value); } }
public class Yen : BaseCurrency { public Yen(double temp) { this.Value = temp; this.Currency = CurrencyEnum.Yen; }
public static implicit operator Dollar(Yen yen) { return new Dollar(0.0097 * yen.Value); }
public static implicit operator Euro(Yen yen) { return new Dollar(0.0072 * yen.Value); } }
public class Program { static void Main(string[] args) { Euro eurobetrag = new Euro(20); Dollar dollarbetrag = eurobetrag; Yen yenbetrag = eurobetrag; Console.WriteLine("{0}{1} sind...", eurobetrag.Value, eurobetrag.Currency); Console.WriteLine("{0}{1}",dollarbetrag.Value, dollarbetrag.Currency); Console.WriteLine("{0}{1}", yenbetrag.Value, yenbetrag.Currency);
Yen y = new Yen(2026); Euro e = new Euro(14.8); Dollar d = e + y;
Console.WriteLine("-------------------"); Console.WriteLine("{0}{1}",d.Value, d.Currency);
#region Press any key... #if DEBUG Console.WriteLine("Press any key to close..."); Console.ReadLine(); #endif #endregion } } } |
vielen dank für (noch eine) antwort -> DANN wäre die aufgabe zum glück KOMPLETT gelöst
MFG
Ralf Jansen - Mi 05.02.14 16:04
Zitat: |
C#-Quelltext 1: 2: 3: 4:
| public static implicit operator Euro(Yen yen) { return new Dollar(0.0072 * yen.Value); } | |
Was fällt dir auf.
Nebenbei gesagt muß das, wenn es denn dann richtig programmiert ist, dann auch nicht passen. Echte Währungskurse funktionieren so nicht. Will sagen die Umwandlung Euro -> Yen -> Dollar entspricht nicht dem direkten von Euro -> Dollar. Währungskurse werden unabhängig ermitteln.
derprogrammier69 - Do 06.02.14 02:35
[kommentarlos]
danke!
Palladin007 - Do 06.02.14 11:08
Das Risiko einer Copy-Paste-Arbeitsweise ;)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!