web-dev-qa-db-fra.com

Aucune exception de débordement pour int en C #?

J'ai eu cette expérience étrange avec le problème numéro 10 sur Project Euler (excellent site d'ailleurs). La tâche consistait à calculer la somme de tous les nombres premiers inférieurs à deux millions.

J'ai utilisé un int pour la somme, et mon algorithme a produit une réponse, mais quand je l'ai collé pour vérifier la réponse, c'était faux.

Il s'est avéré que le résultat était trop grand pour tenir dans un int, mais cela ne provoquerait-il pas une erreur de débordement ou quelque chose? Au lieu de cela, il a juste renvoyé une valeur loin de la vraie réponse.

Quand j'ai changé le type en long, tout était dory hunky.

56
erikric

Les opérations sur les nombres entiers C # ne génèrent pas d'exceptions en cas de débordement par défaut. Vous pouvez y parvenir via les paramètres du projet ou en faisant le calcul checked:

int result = checked(largeInt + otherLargeInt);

Maintenant, l'opération va lancer.

L'opposé est unchecked, ce qui rend toute opération explicitement décochée. De toute évidence, cela n'a de sens que lorsque les opérations vérifiées sont activées dans les paramètres du projet.

88
Konrad Rudolph

En C # an OverflowException n'est pas levé (dans VB l'exception est levée par défaut).

Pour obtenir l'excpetion, vous devez intégrer votre code dans un contexte checked:

byte value = 241;
checked
{
    try 
    {
        sbyte newValue = (sbyte) value;
        Console.WriteLine("Converted the {0} value {1} to the {2} value {3}.", 
            value.GetType().Name, value, 
            newValue.GetType().Name, newValue);
    }
    catch (OverflowException) 
    {
        Console.WriteLine("Exception: {0} > {1}.", value, SByte.MaxValue);
    }
}       

MSDN explique plus en détail:

Pour que l'opération arithmétique, de conversion ou de conversion lève une exception OverflowException, l'opération doit se produire dans un contexte vérifié. Par défaut, les opérations arithmétiques et les débordements dans Visual Basic sont vérifiés; en C #, ils ne le sont pas. Si l'opération se produit dans un contexte non contrôlé, le résultat est tronqué en ignorant tous les bits de poids fort qui ne correspondent pas au type de destination.

20
Dirk Vollmar

C'est parce que, par défaut, C # ne lève aucune exception pour le débordement d'entier ainsi que le sous-dépassement. Il y a quelques choses que vous pouvez faire ici.

Option 1

Vous devez activer la levée de l'exception en accédant à Projet => propriétés => onglet Génération => Avancé => vérifier le dépassement de capacité de dépassement arithmétique. (Assurez-vous de cocher l'option)

enter image description here

Assurez-vous de cocher l'option

Option 2

Utilisez un bloc coché et lancez une exception de débordement pour gérer la situation. Un exemple d'extrait de code serait

        try
        {
            checked
            {
                int y = 1000000000;
                short x = (short)y;
            }
        }
        catch (OverflowException ex)
        {
            MessageBox.Show("Overflow");
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error");
        }

J'espère que cela vous aidera... :)

15
oshan2csd

j'ai déjà ajouté un cmt, mais c'est peut-être intéressant pour certains d'entre vous:

msdn nous dit:

Le débordement arithmétique entier déclenche une OverflowException ou rejette les bits les plus significatifs du résultat

mais

Le débordement arithmétique décimal lève toujours une exception OverflowException.

aussi

En cas de dépassement d'entier, ce qui se produit dépend du contexte d'exécution, qui peut être vérifié ou décoché. Dans un contexte vérifié, une OverflowException est levée. Dans un contexte non contrôlé, les bits les plus significatifs du résultat sont ignorés et l'exécution se poursuit. Ainsi, C # vous donne le choix de gérer ou d'ignorer le débordement.

7
Andreas Niedermair

Par défaut, C # ne vérifie pas le dépassement arithmétique sur les entiers. Vous pouvez changer cela avec le /checkedoption du compilateur ou en activant "Vérifier les débordements/débordements arithmétiques" dans Visual Studio (propriétés du projet - Build - Advanced).

Vous pouvez utiliser checked et unchecked mots-clés pour remplacer la valeur par défaut au cas par cas. Si vous comptez sur la vérification dans un morceau de code, l'activer explicitement à l'aide de checked serait une bonne idée.

int j = checked(i * 2);

checked
{
    int j = i * 2;
    // Do more stuff
}

Notez que les opérations en virgule flottante ne jettent jamais un OverflowException, et les opérations décimales jettent toujours un OverflowException. Voir aussi opérateurs C # .

6
Thorarin