L’opérateur “>” ne peut pas être appliqué aux types ‘ulong’ et ‘int’

Je suis curieux de savoir pourquoi le compilateur C # ne me donne qu’un message d’erreur pour la deuxième instruction if.

enum Permissions : ulong { ViewListItems = 1L, } public void Method() { int mask = 138612833; int compare = 32; if (mask > 0 & (ulong)Permissions.ViewListItems > 32) { //Works } if (mask > 0 & (ulong)Permissions.ViewListItems > compare) { //Operator '>' cannot be applied to operands of type 'ulong' and 'int' } } 

J’ai expérimenté cela en utilisant ILSpy pour examiner le résultat, et c’est ce que j’ai découvert.

Évidemment, dans votre deuxième cas, il s’agit d’une erreur – vous ne pouvez pas comparer un ulong et un int car il n’y a pas de type auquel vous pouvez contraindre les deux. Un ulong peut être trop gros pour un long et un int peut être négatif.

Dans votre premier cas, cependant, le compilateur est malin. Il se rend compte que const 1 > const 32 n’est jamais vrai et n’inclut pas votre instruction if dans la sortie compilée. (Cela devrait donner un avertissement pour le code inaccessible.) C’est la même chose si vous définissez et utilisez un const int plutôt qu’un littéral, ou même si vous convertissez le littéral explicitement (c’est-à-dire (int)32 ).

Mais alors le compilateur ne réussit-il pas à comparer un ulong avec un int , ce qui, nous l’avons dit, était impossible?

Apparemment non. Alors qu’est ce qui se passe?

Essayez plutôt de faire quelque chose dans les lignes suivantes. (Prendre les entrées et écrire les sorties pour que le compilateur ne comstack rien.)

 const int thirtytwo = 32; static void Main(ssortingng[] args) { ulong x = ulong.Parse(Console.ReadLine()); bool gt = x > thirtytwo; Console.WriteLine(gt); } 

Cela comstackra, même si ulong est une variable et même si le résultat n’est pas connu au moment de la compilation. Jetez un coup d’œil à la sortie dans ILSpy:

 private static void Main(ssortingng[] args) { ulong x = ulong.Parse(Console.ReadLine()); bool gt = x > 32uL; /* Oh look, a ulong. */ Console.WriteLine(gt); } 

Ainsi, le compilateur traite en fait votre const int comme un ulong . Si vous faites thirtytwo = -1 , la compilation du code échoue, même si nous soaps alors que gt sera toujours vrai. Le compilateur lui-même ne peut pas comparer un ulong à un int .

Notez également que si vous faites x un long au lieu d’un ulong , le compilateur génère 32L lieu de 32 sous forme d’entier, même s’il n’est pas obligé de le faire. (Vous pouvez comparer un int et un long au moment de l’exécution.)

Cela indique que le compilateur ne traite pas 32 comme un ulong dans le premier cas, car il doit le faire, simplement parce qu’il peut correspondre au type de x . Cela évite au temps d’exécution de contraindre la constante, et il ne s’agit que d’un bonus lorsque la contrainte ne devrait pas être possible de plein droit.

Ce n’est pas le CLR donnant ce message d’erreur, c’est le compilateur.

Dans votre premier exemple, le compilateur traite 32 comme ulong (ou un type implicitement convertible en ulong par exemple uint ), tandis que dans votre deuxième exemple, vous avez explicitement déclaré le type sous la forme d’un int . Il n’y a pas de surcharge de l’opérateur > qui accepte un ulong et un int et vous obtenez donc une erreur du compilateur.

Les réponses de rich.okelly et de rawling expliquent correctement pourquoi vous ne pouvez pas les comparer directement. Vous pouvez utiliser la méthode ToUInt64 de la classe Convert pour promouvoir l’int.

 if (mask > 0 & (ulong)Permissions.ViewListItems > Convert.ToUInt64(compare)) { }