Laden...

Warum können objects mit einem Werttypen, nicht in einen anderen Werttypen gecastet werden?

Erstellt von Scavanger vor 3 Jahren Letzter Beitrag vor 3 Jahren 710 Views
Scavanger Themenstarter:in
309 Beiträge seit 2008
vor 3 Jahren
Warum können objects mit einem Werttypen, nicht in einen anderen Werttypen gecastet werden?

Servus,

ich hab eine Verständnis frage:

Ursprünglich wollte ich folgendes machen:


List<uint> l1 = new List<uint> { 1, 2, 3 };
var l2 = l1.Cast<int>().ToList();

Das wirft > Fehlermeldung:

System.InvalidCastException: "Unable to cast object of type 'System.UInt32' to type 'System.Int32'."

Nun ja, das lässt sich ja einfach mit


var l2 = l1.Select(i => (int)i).ToList();

ersetzen, kein Problem.

Aber irgenwie hat mir das keine Ruhe gelassen, IEnumerable<T> Cast<T> ist folgendermaßen implementiert:


public static IEnumerable<T> Cast<T>(this IEnumerable source)
{
    foreach (object o in source)
        yield return (T)o;
}

Das Problem ist, dass der Wert in ein object gesteckt wird, dieser Code wirft die gleiche Exception:


uint i = 42;
object o = i;
int j = (int)o;

Erst dachte ich, Werttypen können nicht aus einem object zurück gecastet werden, aber folgerndes funktioniert:


int i = 42;
object o = i;
int j = (int)o;

Warum können objects, mit einem Werttypen, nicht in einen anderen Werttypen gecastet werden? Vor allem da ja in der Exception die korrekten Typen genannt werden, also warum kann er den Cast nicht ausführen?

using System;class H{static string z(char[]c){string r="";for(int x=0;x<(677%666);x++)r+=c[
x];return r;}static void Main(){int[]c={798,218,229,592,232,274,813,585,229,842,275};char[]
b=new char[11];for(int p=0;p<((59%12));p++)b[p]=(char)(c[p]%121);Console.WriteLine(z(b));}}

5.657 Beiträge seit 2006
vor 3 Jahren

Weeks of programming can save you hours of planning

16.807 Beiträge seit 2008
vor 3 Jahren

Bei der "Umwandlung" von uint auf int handelt es sich im Endeffekt nicht um ein Cast sondern um ein Reassigment.
Hier brauchst Du die Convert.To-Methoden.

Das Problem ist, dass der Wert in ein object gesteckt wird, dieser Code wirft die gleiche Exception:

Die Exception selbst kommt im Prinzip vom Unboxing:
Deine Quelle ist uint; aber das Unboxing erfolgt auf int - daher knallts.

Bezogen auf Dein Beispiel bräuchtest Du einen zusätzlichen Cast; dann klappts.
=> uint -> object -> uint -> int

uint i = 42;
object o = i;
int j = (int)(uint)o;

Aber => uint -> object -> int knallt.
Dass der "Cast" von unit auf int funktioniert liegt am expliziten Operator.

 public static implicit operator int(uint value) => Convert.ToInt32(value);

Dein Szenario deckt aber so Cast<T> nicht ab.
Cast ist eigentlich dafür da, dass Du zB. eine Collection eines Interfaces hast, das dann wiederum verschiedene Instanzen von Implementierungen hast, und dann durch das Cast die Implementierungen raus ziehen kannst.

W
955 Beiträge seit 2010
vor 3 Jahren

Die Signatur sollte aber explicit sein, schließlich willst du ja ausdrücken dass nicht jedes uint in ein int umgewandelt werden kann und der Programmierer casten soll.

Scavanger Themenstarter:in
309 Beiträge seit 2008
vor 3 Jahren

@MrSparkle:
Ich weiß, es mir nur klar zu machen um was es mir geht.

@Abt:
Super danke, an das Unboxing hab ich nicht gedacht. 👍

using System;class H{static string z(char[]c){string r="";for(int x=0;x<(677%666);x++)r+=c[
x];return r;}static void Main(){int[]c={798,218,229,592,232,274,813,585,229,842,275};char[]
b=new char[11];for(int p=0;p<((59%12));p++)b[p]=(char)(c[p]%121);Console.WriteLine(z(b));}}