2010-02-25 3 views
4

J'essaie d'obtenir une différence entre les méthodes de coulée de type.Différentes méthodes de conversion de type. Quelle est la différence

par ex.

Méthode 1

public byte fun() 
{ 
    object value=1; 
    return (byte)value; // this gives me error 
} 

Méthode 2

public byte fun() 
{ 
    object value=1; 
    return byte.Parse(value.ToString()); // this runs 
} 

Méthode 3

public byte fun() 
{ 
    object value=1; 
    return Convert.ToByte(value); // this runs 
} 

Quelle est la différence entre tous les trois. Comment ils travaillent en interne. Quels sont le type de valeur et le type de réfrence ici. Quelle fonction peut convertir le type de valeur type ref et vice versa

Edit 2

Quand j'écrit ce que la ligne type de données « 1 » seront traités par int32 par défaut, octet ou autre chose.

valeur d'objet = 1;

+0

De plus il y a 'bool byte.TryParse (string, out double valeur)' – AxelEckenberger

+0

@Obalix: devrait être byte.TryPase (chaîne, out byte valeur) –

Répondre

8

Il y a beaucoup de questions ici.

La méthode 1 échoue car vous ne pouvez pas effectuer une unbox et un cast en une seule opération. Vous définissez "valeur" à un nombre entier encadré. Lorsque vous essayez d'effectuer le cast, vous déballez l'entier et essayez de lancer un octet en une seule opération, ce qui échoue. Cela fonctionne, BTW:

return (byte)((int)value)); // Unbox, then cast, in two operations 

Méthode 2 fonctionne parce que vous convertissez l'entier à une chaîne, puis en utilisant byte.Parse pour le convertir en un octet. C'est très cher, car ça va de/à partir des chaînes.

La méthode 3 fonctionne car elle voit que l'objet en valeur est IConvertible (int) et utilise l'opération de conversion appropriée pour convertir en octet. C'est probablement un moyen plus efficace de l'aborder, dans ce cas. Puisque "value" stocke un int, et que int supporte IConvertible, Convert.ToByte effectuera une vérification null, puis appellera Convert.ToByte (int), ce qui est assez rapide (il vérifie les limites, et un cast direct).

Je vous recommande de lire le billet de blog d'Eric Lippert intitulé Representation and Identity. Il couvre la coulée en détail, et explique pourquoi la méthode 1 échoue ...

1
// This is a direct cast. It expects that the object 
// in question is already allocated as the data type 
// indicated in the cast 
(byte)value; 

// This is a direct code conversion. It takes the argument 
// and runs through code to create a new variable of the 
// type byte. You'll notice if you include this in different 
// code that value will still be an object but your new 
// data will be a byte type 
byte.Parse(value.ToString()); 

// This will convert any object similarly to the byte.Parse. 
// It is not as fast because it does not have a definitely 
// typed parameter (as parse has string). So it must go 
// through a couple of extra steps to guarantee the conversion 
// is smooth. 
Convert.ToByte(value); 

La coulée directe est toujours la plus rapide. Il suppose que le type est déjà établi et alloué donc tout ce qu'il a à faire est de changer son type de référence en mémoire. Les méthodes de conversion sont des conversions de code, elles nécessitent donc un peu plus de temps. Je ne connais pas les benchmarks, mais Parse est un peu plus rapide car il traite d'une entrée spécifique et d'une sortie spécifique (chaîne-> octet). Convert est la plus lente des méthodes de conversion car elle n'a pas cette même spécificité.

+0

Sa méthode n'est pas une distribution directe, cependant ... c'est un casting unbox +, qui échouera. –

+0

En outre, Convert est plus rapide, car il peut utiliser int.ToByte (à partir de IConvertible.ToByte) directement. –

+0

@Reed Copsey: Ce serait unboxing s'il était initialement instancié comme un octet. Ce n'était pas le cas, il a commencé sa répartition en tant qu'objet. Pour qu'il soit "déballé", il doit d'abord être encadré d'octet en objet. Dans ce cas, c'est une conversion directe et c'est pourquoi elle échoue. Voir: http://msdn.microsoft.com/en-us/library/b95fkada(VS.80).aspx et http://msdn.microsoft.com/en-us/library/ms173105(VS.80). aspx –

0

Eh bien voici mon coup à elle:

Méthode 1

Ceci est une distribution de type, à savoir la valeur doit être d'un type qui peut être implcitly ou explicitement converti en un octet. De plus, la valeur ne doit pas être en dehors des limites d'un octet.

L'appel échoue car le compilateur ne dispose d'aucune information sur le type d'objet à partir duquel il doit être converti et ne peut donc pas effectuer de conversion implicite ou explicite. Faire

int obj = 1; 
byte b = (byte) obj; 

ou

byte b = (byte) (int) obj; 

œuvres. La deuxième option utilise unboxing expictif (fournissant ainsi l'information nécessaire) comme décrit dans le commentaire et la publication de Reed Copsey. Le link fourni par le commentaire de Reed Copsey explique cela en détail.

Pour les conversions d'objets personnalisés, les conversions implicites et explicites sont des opérateurs qui sont des méthodes statiques définies dans la classe. Pour object aucune opération implicite ou explicite n'existe (voir link pour la raison pourquoi), alors que pour int ces opérations existent.

Méthode 2

Ici vous analysez une chaîne de la valeur de la chaîne doit être un nombre qui est à l'intérieur la limite d'un octet. Ici, vous pouvez également utiliser TryParse qui vous permet de vérifier si la conversion va réussir.

Méthode 3

Utilise la conversion de type de la classe Convert. C'est la méthode la plus flexible qui supporte la plupart des types communs. Ici, la valeur doit être convertible en un nombre, et la valeur doit être dans les limites de l'octet. La classe Convert utilise IConvertible pour convertir entre les différents types et, par conséquent, est extensible.

+1

Votre explication "Méthode 1" est incorrecte. C'est une restriction spécifique sur unboxing -ie: unboxing un type T ne peut être déboché que sur T directement. Voir: http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx –

+0

Vous ne savez pas si ce lien contredit ma déclaration ...Je suppose que 'int jjj = (int) (short) ooo;' est la déclaration que vous avez en tête. Comme je l'interprète, c'est l'équivalent de 'short s = (short) ooo; int i = (int) court; Et ce comportement serait conforme à ce que j'ai écrit. – AxelEckenberger

+0

Il ne s'agit pas du compilateur "ne disposant d'aucune information sur le type d'objet à lancer", mais plutôt que le type diffère lorsque vous déballez, et que vous ne pouvez pas décompresser + lancer en une seule opération. –

Questions connexes