none
implicit operator bei Lambda Ausdrücken RRS feed

  • Frage

  • Hallo liebe Community,

    ich habe folgende Frage: Wie wird bei einem Lambda Ausdruck der Datentyp bestimmt wenn KEIN expliziter Cast vorhanden ist?

    Beispiel Klasse:

    public class TestClass { /// <summary> /// Value /// </summary> public object Value { get; set; }

    /// <summary> /// Automatic casting from TestClass to decimal. /// </summary> public static implicit operator decimal(TestClass x) { return Convert.ToDecimal(x.Value); }

    /// <summary> /// Automatic casting from TestClass to int. /// </summary> public static implicit operator int(TestClass x) { return Convert.ToInt32(x.Value); } /// <summary> /// Automatic casting from TestClass to double. /// </summary> public static implicit operator double(TestClass x) { return Convert.ToDouble(x.Value); } }

    Beispiel Aufruf:

    static void Main(string[] args) { TestClass v1 = new TestClass() { Value = 1.22 }; TestClass v2 = new TestClass() { Value = 5.43 }; List<TestClass> values = new List<TestClass>() { v1, v2 };

    object test = values.Sum(v => v); }

    Warum wird bei dem Aufruf object test = values.Sum(v => v); Int32 verwendet?

    Vielen Dank, Christof

    Dienstag, 17. Juli 2012 09:25

Antworten

  • Hallo,

    ändern kannst Du das Verhalten einfach: Verwende einen expliziten Cast.

    Stefans Aussage mal etwas aufgedröselt:
    Zunächst stellt der Compiler die möglichen Überladungen von Enumerable.Sum() fest.
    Dann berücksichtigt er Deine Benutzer-Konvertierungen und sucht dort die "kleinste" passende heraus, was in Deinem Falle ein Integer wäre.
    Hättest Du eine Überladung für short (oder byte) nähme er auch diese, und die eingebaute implizite Konvertierung für int verwenden.

    Gäbe es wiederum nur eine Konvertierung auf long, so würde der diese Verwenden und die entsprechende Überladung für Sum.

    Gibt es nur die beiden Konvertierungen mit double und decimal kann der Compiler das nicht auflösen,
    da es keine implizite Konvertierung  (siehe Anmerkungen!) zwischen den decimal und Fließkommatypen gibt
    und so würde ein Fehler erzeugt.

    Genauer und weniger umgangssprachlich steht es in der C# Sprachspezifikation
    (insbes. Abschnitte 6. Conversions, 7.5.3 Overload resolution - Achtung: Kopfschmerzen drohen!)

    Deine impliziten Benutzerkonvertierungen sind hoffentlich nur für den Test entstanden,

    denn im Sinne einer impliziten Konvertierung sind sie nicht.
    Die sollte nur vorgenommen werden wenn kein Datenverlust  (und keine Ausnahme) auftreten kann.
    Siehe auch Konvertierungsoperatoren

    Zum Abschluss:
    Ich würde immer den expliziten Weg vorgeben anstatt mir in der C# Sprachspezifikation ein Löchlein zu suchen
    (und mehrmals Kopfschmerzen zu holen ;-) Denn das führt nur zu Frust beim Verwenden der Klassen.

    Gruß Elmar

    • Als Antwort markiert Christof_Sbg Mittwoch, 18. Juli 2012 05:20
    Dienstag, 17. Juli 2012 14:09
    Beantworter

Alle Antworten

  • Wenn ich mich recht erinnere: weil Enumerable.Sum() als erstes auf die Int32-Signatur prüft. Diese findet und damit zufrieden ist.
    Dienstag, 17. Juli 2012 11:57
  • Hallo Stefan,

    vielen Dank für deine Rückmeldung.

    Gib es auch einen Grund warum dies so ist bzw. kann man dieses Verhalten übersteuern?
    Kennt jemand eine MSDN Seite dazu? Habe leider noch keine gefunden.

    Dienstag, 17. Juli 2012 13:41
  • Hallo,

    ändern kannst Du das Verhalten einfach: Verwende einen expliziten Cast.

    Stefans Aussage mal etwas aufgedröselt:
    Zunächst stellt der Compiler die möglichen Überladungen von Enumerable.Sum() fest.
    Dann berücksichtigt er Deine Benutzer-Konvertierungen und sucht dort die "kleinste" passende heraus, was in Deinem Falle ein Integer wäre.
    Hättest Du eine Überladung für short (oder byte) nähme er auch diese, und die eingebaute implizite Konvertierung für int verwenden.

    Gäbe es wiederum nur eine Konvertierung auf long, so würde der diese Verwenden und die entsprechende Überladung für Sum.

    Gibt es nur die beiden Konvertierungen mit double und decimal kann der Compiler das nicht auflösen,
    da es keine implizite Konvertierung  (siehe Anmerkungen!) zwischen den decimal und Fließkommatypen gibt
    und so würde ein Fehler erzeugt.

    Genauer und weniger umgangssprachlich steht es in der C# Sprachspezifikation
    (insbes. Abschnitte 6. Conversions, 7.5.3 Overload resolution - Achtung: Kopfschmerzen drohen!)

    Deine impliziten Benutzerkonvertierungen sind hoffentlich nur für den Test entstanden,

    denn im Sinne einer impliziten Konvertierung sind sie nicht.
    Die sollte nur vorgenommen werden wenn kein Datenverlust  (und keine Ausnahme) auftreten kann.
    Siehe auch Konvertierungsoperatoren

    Zum Abschluss:
    Ich würde immer den expliziten Weg vorgeben anstatt mir in der C# Sprachspezifikation ein Löchlein zu suchen
    (und mehrmals Kopfschmerzen zu holen ;-) Denn das führt nur zu Frust beim Verwenden der Klassen.

    Gruß Elmar

    • Als Antwort markiert Christof_Sbg Mittwoch, 18. Juli 2012 05:20
    Dienstag, 17. Juli 2012 14:09
    Beantworter
  • Vielen Dank

    Mittwoch, 18. Juli 2012 05:19