2008-10-07 12 views
2

Tout d'abord, deux exemples:question de boxe

// This works 
int foo = 43; 
long lFoo = foo; 

// This doesn't 
object foo = (int)43; 
long? nullFoo = foo as long?; // returns null 
long lFoo = (long)foo; // throws InvalidCastException 
if (foo.GetType() == typeof(int)) 
    Console.WriteLine("But foo is an int..."); // This gets written out 

Maintenant, je pense que la raison pour laquelle la seconde ne fonctionne pas est à cause de la boxe. Le but de ce code est de mettre en œuvre IComparable. J'ai besoin d'un moyen de contraindre un objet en un long ou un ulong selon le cas, ou si ce n'est ni l'un ni l'autre, que de lancer une erreur. Je ne veux pas avoir à implémenter des contrôles pour chaque type numérique de base (byte, int, long, ubyte, ...) Je préfère les attraper avec le plus grand type numérique et le traiter de cette façon. Pensées de tous les gens intelligents ici? Comment puis-je déballer l'objet, évitant de préférence la réflexion, mais je suppose que si c'est le seul moyen ... Ou devrais-je simplement ne pas implémenter la version non générique de IComparable?

Edit:

Cela semble fonctionner, mais semble horrible bidouille autour du problème. Est ce juste moi?

long lFoo = long.Parse(foo.ToString()); 
+0

Je serais intéressé de voir exactement pourquoi vous avez besoin de le faire. Comment cela se rapporte-t-il à IComparable? –

Répondre

7
object foo = (int) 43; 
long lFoo = ((IConvertible) foo).ToInt64(null); 
+0

Cela fonctionne réellement ... Vive les types de base qui héritent des interfaces. Jamais tout à fait compris cette partie, mais utile néanmoins. –

4

Lorsque vous coulée à un type de valeur que vous forcez vraiment une Unbox IL opération, qui exige que le type que vous casting de matchs exactement la valeur en boîte; il n'y a pas de conversions, implicites ou explicites, qui peuvent se produire en même temps. Cela signifie généralement que vous devez effectuer un changement en utilisant le typecode (ou un if/else si vous utilisez des types), ou, dans votre cas, aller avec une vérification de null suivie de Convert.ToInt64(), qui devrait traiter avec correctement.

+0

Il ne nécessite pas de correspondance * exact *. Vous pouvez déballer une énumération encadrée comme type sous-jacent ou vice versa (malgré les informations de type qui s'y trouvent réellement). Vous pouvez également décocher un type nullable approprié. Il y a des conversions impaires similaires que le CLR permet, comme int [] to uint []. –

0

Ce n'est pas seulement vous, mais tryparse ne déclenche pas d'exception.

object foo = (int)43; 
long outVal; 
if(long.TryParse(foo.ToString(),out outVal)) 
{ 
//take action with correct value of long 
} 
else 
{ 
//maybe passed you another type of object 
} 
+0

Ce n'est * pas * le chemin à parcourir. En plus d'être beaucoup plus inefficace, je crois qu'il n'y a aucune garantie que le format de chaîne généré par ToString() puisse être analysé immédiatement par Parse/TryParse() (c'est-à-dire pas dans tous les curtures) – tomasr