Pour obtenir une clé
d'essai remplissez le formulaire ci-dessous
Demandez des tariffs
Nouvelle licence
Renouvellement de licence
--Sélectionnez la devise--
USD
EUR
RUB
* En cliquant sur ce bouton, vous acceptez notre politique de confidentialité

Free PVS-Studio license for Microsoft MVP specialists
To get the licence for your open-source project, please fill out this form
** En cliquant sur ce bouton, vous acceptez notre politique de confidentialité.

I am interested to try it on the platforms:
** En cliquant sur ce bouton, vous acceptez notre politique de confidentialité.

Votre message a été envoyé.

Nous vous répondrons à


Si vous n'avez toujours pas reçu de réponse, vérifiez votre dossier
Spam/Junk et cliquez sur le bouton "Not Spam".
De cette façon, vous ne manquerez la réponse de notre équipe.

>
>
>
V3161. Comparing value type variables w…
Analyzer diagnostics
General Analysis (C++)
General Analysis (C#)
General Analysis (Java)
Diagnosis of micro-optimizations (C++)
Diagnosis of 64-bit errors (Viva64, C++)
Customer specific requests (C++)
MISRA errors
AUTOSAR errors
OWASP errors (C#)
Problems related to code analyzer
Additional information
Contents

V3161. Comparing value type variables with 'ReferenceEquals' is incorrect because compared values will be boxed.

01 Oct 2020

The analyzer has detected a suspicious call of the 'Object.ReferenceEquals' method: either one or both of the passed arguments are of the value type. Since the method's parameters are of type 'Object', arguments of the value type will be boxed when passed to the method. As a result of such boxing, an object will be created on the heap and a reference to that object will be passed to the 'Object.ReferenceEquals' method. Since this reference is not equal to any other reference, the method will return 'false' regardless of the passed argument's value.

Consider a simple synthetic example:

void SyntheticMethod(Point x, object a)
{
  if (Object.ReferenceEquals(x, a))
    ....
}

The variables 'x' and 'a' are passed to the 'Object.ReferenceEquals' method. Since 'x' is of type 'Point', its value will be boxed as it gets cast to type 'Object'. The call to 'Object.ReferenceEquals' will, therefore, always return 'false' no matter what arguments were passed to 'SyntheticMethod'.

This issue can be fixed by replacing the method call with a direct comparison of the values:

void SyntheticMethod(Point x, object a)
{
  if (a is Point pointA && pointA == x)
    ....
}

This rule is also applied to arguments whose types are generic parameters. Unless values for such a parameter are limited to reference types only, the analyzer will issue the warning. For example:

void SomeFunction<T>(T genericObject,
                     object someObject)
{
  if (Object.ReferenceEquals(genericObject, someObject))
    ....
}

Here, 'genericObject' could be an instance of both a reference type and a value type. 'Object.ReferenceEquals' will always return 'false' for value types. Such behavior might be unexpected and unwanted. To make sure that no objects of value types can be passed to the method, limit the parameter accordingly:

void SomeFunction<T>(T genericObject, 
                     object someObject) where T : class
{
  if (Object.ReferenceEquals(genericObject, someObject))
    ....  
}

Now only a reference type can be substituted for the parameter, so the analyzer will no longer issue the warning.

In the following example, the parameter is limited to an interface:

void SomeFunction<T>(T genericObject,
                     object someObject) where T : ICloneable
{
  if (Object.ReferenceEquals(genericObject, someObject))
    ....
}

The analyzer will report this code since value-type objects can implement interfaces. Thus, the limitation 'where T : ICloneable' does not protect the method from being invoked on structures, and such a call may lead to unpredictable results.

There is one specific point about boxing nullable types that we need to discuss separately. They are of the value types, so they will be boxed when they are cast to 'Object'. However, objects of these types are boxed in their own special way. If such a variable has a value, the boxing will allocate the value itself on the heap, rather than the nullable-type object. If the variable has no value, the boxing will return a null reference.

In the following example, 'x' is of type 'Nullable<Point>'. When 'x' is boxed, you are quite possible to get a null reference. In that case, the call of 'Object.ReferenceEquals' will return 'true' if the 'a' argument is 'null' too.

void SyntheticMethod(Point? x, object a)
{
  if (Object.ReferenceEquals(x, a))
    ....
}

However, this code will still trigger the warning because testing two items against 'null' in a way like that is suspicious. A better way to check whether the variables have values is to directly compare them with 'null' or to use the 'HasValue' property:

void SyntheticMethod(Point? x, object a)
{
  if (!x.HasValue && a == null)
    ....
}

More on specifics of nullable types:

This diagnostic is classified as:

Unicorn with delicious cookie
Nous utilisons des cookies pour améliorer votre expérience de navigation. En savoir plus
Accepter