2015-05-22 10 views
5

Ich habe diese Funktion, die den aktuellen Wert überprüft. Wenn der aktuelle Wert (1. Parameter) null oder leer ist, dann verwendet es den Standardwert Sie (2 Paramter)Angegebene Cast nicht gültig mit generischen

public static T ZeroNull<T>(object currentValue, T defaultValue) 
{ 
    if (currentValue.Equals(DBNull.Value)) 
     return (T)defaultValue; 
    else if (currentValue.Equals(string.Empty)) 
     return (T)defaultValue; 
    else 
     return (T)currentValue; 
} 

Der obige Code übergeben ordnungsgemäß funktioniert, teilweise ... Aber wenn ich den Code wie dies, es wirft eine "angegebene Umwandlung ist ungültig ..."

float currValue = 20.1f; 
int i = ZeroNull<int>(currValue, 0); // Specified cast is not valid 

int i = ZeroNull<int>("10", 0); // Specified cast is not valid 

Anybody den obigen Code Schnipsel verbessern? Und warum der Compiler diesen Fehler verursacht?

Grüße, Jessie

+0

Das Problem ist, dass 'currValue' ist ein Box-Schwimmer (20.1f) und Ihr versucht, auf einen int unbox, die nicht gültig ist. Das gleiche gilt für "10" – chomba

+0

Danke chomba, aber warum es keinen Fehler macht, wenn ich das tue. 'code'float currValue = 10.2f; 'code'int newCurrValue = (int) currValue; Ich nehme nur an, sie haben die gleiche Logik? – klaydze

+0

Das liegt daran, dass Sie nur explizit zwischen Werttypen umwandeln. Wenn Sie jedoch ein Feld mit einem Werttyp erstellen, müssen Sie es zuerst für den zugrunde liegenden Typ entpacken. – chomba

Antwort

4

Sie könnten versuchen, indem Sie die IConvertible Schnittstelle verwenden, so dass es zumindest für Typen funktioniert, die es implementieren. Hüten Sie sich vor, dies noch Ausnahmen für Typen werfen kann, die Verwendung von ihm nicht machen, aber für Ihre Conversions ganz gut es tut:

public static T ZeroNull<T>(object currentValue, T defaultValue) 
{ 
    if (currentValue.Equals(DBNull.Value)) 
     return (T)defaultValue; 
    else if (currentValue.Equals(string.Empty)) 
     return (T)defaultValue; 
    else 
     return (T)Convert.ChangeType(currentValue,typeof(T)); 
} 

In Bezug auf Ihre Besetzung von float zu int: Sie versuchen, einen Box-Typen zu konvertieren - Es wurde eingerahmt, als du deine Methode aufgerufen hast, die es effektiv in ein Objekt umgewandelt hat. Boxed-Typen können nur an sich selbst zurückgeworfen werden. Da eine Umwandlung in int nicht vom selben Typ ist, funktioniert sie nicht. Zu reproduzieren, ohne Generika dies versuchen, wird es auch eine InvalidCastException werfen:

float currValue = 20.1f; 

object yourValue = currValue; 
int i = (int) yourValue; //throws as well 
+0

Danke für Ihren Vorschlag. Ich habe es versucht und funktioniert gut auf meine aktuelle Anforderung. Ich bleibe bei deinem Vorschlag, bis ich wieder auf eine weitere Ausnahme stoße. :) – klaydze

0

Das Problem, das Sie erleben, ist, dass Sie nicht String in int umwandeln können, das ist, was Sie versuchen, durch Gießen currValue zu tun, um T, wenn T von Typ int ist.

Um eine solche Operation durchzuführen, müssten Sie Convert.ToInt32 oder Int.Parse verwenden. Beides würde dein aktuelles Design untergraben.

Verwandte Themen