ne peut pas convertir le type « string » à 'int? par l'intermédiaire d'une conversion de référence, la conversion de boxe, conversion unboxing, la conversion de l'emballage ou la conversion de type null

StackOverflow https://stackoverflow.com/questions/887943

  •  23-08-2019
  •  | 
  •  

Question

C # accepte ce qui suit:

object o = "hello";
int? i = o as int?;

if (i == null) {
    // o was not a boxed int
}
else {
    // Can use i.Value to recover the original boxed value
}

Mais pas

String o = "hello";
int? i = o as int?;

if (i == null) {
    // o was not a boxed int
}
else {
    // Can use i.Value to recover the original boxed value
}

Je me demande sur le comportement du as mot-clé en C #.

La même chose que dans Java ce échouerait:

Object test1 = "hello";
Integer test2 = (Integer) test1;
String test3 = "hello";
Integer test4 = (Integer) test3; //compilation error
Était-ce utile?

La solution

Le compilateur sait qu'une chaîne ne peut jamais être un int? il vous dit que. Cela ne signifie pas que int? est pas utile. Votre tentative de cas d'utilisation est loin de la normale. La normale est « Je veux représenter un entier et la possibilité que la valeur est manquante / inconnu ». Pour cela, int? fonctionne très bien.

Pourquoi vous attendre votre code d'origine pour travailler? Pourquoi serait-il utile?

Notez que vous peut utiliser as avec des types nullable, pour unboxing:

object o = "hello";
int? i = o as int?;

if (i == null)
{
    // o was not a boxed int
}
else
{
    // Can use i.Value to recover the original boxed value
}

EDIT: Après avoir vu votre commentaire, vous ne l'utilisez pas as pour analyser les choses. Vous voulez probablement utiliser int.TryParse :

string text = "123":
int value;
if (int.TryParse(text, out value))
{
    Console.WriteLine("Parsed successfully: {0}", value);
}
else
{
    Console.WriteLine("Unable to parse text as an integer");
}

Si vous êtes sûr que la chaîne est censée être un entier (il est un bug autrement), alors vous pouvez simplement utiliser int.Parse :

int value = int.Parse(text);

Ce lèveront une exception en cas d'échec l'analyse syntaxique.

Notez également que ces deux méthodes vous permet de spécifier un fournisseur de format (généralement une information de culture) qui vous permet d'exprimer la façon dont les chiffres sont exprimés dans ce format (par exemple des milliers séparateurs).

EDIT: En réponse à votre question nouvelle, le compilateur empêche cela parce qu'il connaît une chaîne ne peut pas peut un int boxed - la conversion ne jamais réussir. Quand il sait seulement que la valeur d'origine est un objet, il peut réussir.

Par exemple, supposons que je vous ai dit, « est ici une forme: est-il un carré » C'est une question sensible. Il est raisonnable de demander:. Vous ne pouvez pas dire sans regarder la forme

Par contre, si je dis: « Voici un triangle: est-il un carré » Ensuite, vous seriez raisonnablement en droit de rire de mon visage, comme un triangle ne peut peut-être un carré -. La question n'a pas de sens

Autres conseils

int? désigne un type entier annulable, pas un int qui pourrait contenir tout autre type de variable.

Si vous voulez un type de variable qui pourrait contenir un int ou une chaîne, vous auriez à utiliser un objet, ou une chaîne, je suppose, et vivre une vie remplie de coulée de type. Je ne sais pas pourquoi vous voulez le faire, cependant.

int? vous permet de stocker une valeur entière, ou une valeur nulle. Ce qui est utile lorsque vous dire la réponse à la question « Combien de commandes a cette personne placée » est légitimement « Je ne sais pas » au lieu d'un certain nombre de commandes, ou zéro, ce qui serait « Je sais pertinemment que cette personne n'a jamais passé une commande ».

Je veux ajouter un peu plus d'informations.

Un autre cas, pourquoi la distribution est invalide et le compilateur renvoie une erreur sur la compilation est que System.String est marqué comme scellé . Ainsi, le compilateur sait de quels types System.String inherites et à quels types vous pouvez lancer la chaîne en utilisant la -operator.

En raison du mot-clé scellé , le compilateur sait aussi que vous ne peuvent pas hériter de System.String pour ajouter des fonctionnalités ou mettre en œuvre des interfaces supplémentaires .

Le code ci-dessous est un exemple et le compilateur jetteront l'erreur suivante sur la compilation

  

Impossible de convertir le type 'SealedClass' à   « ICastToInterface » par l'intermédiaire d'une référence   la conversion, la conversion de la boxe,   conversion unboxing, emballage   conversion, ou de la conversion de type null

public class UnsealedClass {
  // some code
}

public sealed class SealedClass {
  // some code
}

public interface ICastToInterface {
  // some code
}

public class Test {

  public Test() {
    UnsealedClass unsealedClass = new UnsealedClass();

    SealedClass sealedClass = new SealedClass();

    ICastToInterface unsealedCast = unsealedClass as ICastToInterface;  // This works fine

    ICastToInterface sealedCast = sealedClass as ICastToInterface; // This won´t compile, cause SealedClass is sealed
  }
}

mais vous pouvez vérifier la valeur de null et réglez-le sur null.

int? blah;
if (blah == null)
{}

int? est un entier annulable, il n'a rien à voir avec la coulée et le mot-clé comme. « String » est un objet de type chaîne, qui ne peut être converti en un int (ou annulable non nulle).

en tant que mots-clés est pratiquement la même que la coulée en utilisant les supports à l'exception de celle-ci ne renvoie une erreur, il va mettre l'objet à null:

int i = 1;

object o = i; //boxing

int j = (int)o; //unboxing

Ce premier exemple fonctionne comme l'objet assigné à o est un entier.

Considérons maintenant:

string i = "MyString";

object o = MyString;

 int j = (int)o //unboxing raises exception

 int j = o as int; //raises compilation Error as int is not nullable
 int? j = o as int?; /// o == null

J'espère que cela aide à expliquer la différence entre les deux concepts.

Richard

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top