La définition d'une structure définit en fait deux types : un type de valeur et un type de classe qui dérive de System.ValueType
. Si une demande est faite pour créer une variable, un paramètre, un champ ou un tableau (collectivement, "emplacement de stockage") d'un type dérivé de System.ValueType, le système créera un emplacement de stockage qui stockera les champs de l'objet plutôt qu'une référence à un objet dans lequel ces champs apparaissent. En revanche, si une demande est faite pour créer une instance d'un type dérivant de System.ValueType, le système créera une instance d'objet d'une classe dérivant de System.ValueType.
Pour s'en convaincre, il suffit de créer une structure qui implémente IValue :
interface IValue {int value {get; set;}};
struct ValueStruct : IValue
{
public int value {get; set;}};
}
avec une routine de test générique et du code pour l'intégrer :
static void Test<T>(T it) where T:IValue
{
T duplicate = it;
it.value += 1;
duplicate.value += 10;
Console.WriteLine(it.value.ToString());
}
static void Test()
{
ValueStruct v1 = new ValueStruct();
v1.value = 9;
IValue v2 = v1;
Test<ValueStruct>(v1);
Test<ValueStruct>(v1);
Test<IValue>(v1);
Test<IValue>(v1);
Test<IValue>(v2);
Test<IValue>(v2);
}
Notez que dans tous les cas, l'appel à GetType sur le paramètre passé à Test produirait ValueStruct, qui se déclarerait lui-même comme un type de valeur. Néanmoins, l'élément passé ne sera un "vrai" type de valeur que lors des deux premiers appels. Lors des troisième et quatrième appels, il s'agira en réalité d'un type de classe, comme le montre le fait qu'une modification de duplicate
affectera it
. Lors des cinquième et sixième appels, la modification sera propagée à la v2, de sorte que le deuxième appel la "verra".
3 votes
La performance est-elle vraiment importante, car il s'agit en fait d'une micro-optimisation ?
6 votes
Les méthodes 2 et 3, telles qu'elles sont rédigées, ne sont pas valables.
obj == null ||
renvoie un résultat positif pour les types de référence.default(T) != null
renverra un message faux pour l'élémentNullable<T>
des structures.4 votes
Votre modification de la méthode 2 ne sera toujours pas valable.
obj != null ||
renvoie un résultat positif pour les objets de type référence non nuls.0 votes
@PoweRoy, si je le fais souvent, je suis sûr que ça ne fera pas de mal de le faire de la bonne façon.
3 votes
Puisque je suis hypercritique, euh, je veux dire utile, la méthode 1 n'aime pas les nullités.
Nullable<T>
objets.int? bar = null;
Si vous passez cela dans la fonction, vous obtiendrez false. (Je ne m'attendais pas à cela, pour être honnête).3 votes
Méthode 2 : dernière modification.
return obj == null ? false : ...
pose toujours un problème pour lesNullable<T>
.0 votes
@Anthony, pourquoi pas maintenant ?
0 votes
@smartcaveman, oui, admettre la défaite. Je pense que vous êtes sur la bonne voie en suivant la réponse de Marc, les trois méthodes que vous avez présentées (et leurs diverses itérations) ont toutes leurs divers problèmes.