2010-08-31 5 views
7

J'ai une structure avec quelques champs. L'un des champs est d'un type générique. Le type générique peut être soit un type de référence, soit un type de valeur.Forcer un type de valeur (générique) à être une référence

Je veux forcer qu'il est stocké comme une référence interne, pour éviter que la structure devienne trop grande.

struct Foo<T> 
{ 
    T field; // should be a reference 
} 

Je sais que je pourrais utiliser object ou T[], mais les deux est maladroit. N'y at-il pas quelque chose comme un type de référence générique?

struct Foo<T> 
{ 
    Reference<T> field; 
} 

Oui, bien sûr, je pourrais écrire le mien. Mais j'essaie d'éviter cela

+0

Je ne comprends pas comment cela résout le problème. Supposons que S est un type de grande valeur. Alors Foo est * la même taille * que S. Si l'utilisateur est bien avec la performance de S alors pourquoi ne seraient-ils pas aussi trouver avec la performance de Foo ? Boxe S - que vous boxiez avec un objet ou votre propre classe de boxe personnalisée - utilisera * plus * d'espace en général, car vous aurez besoin d'espace pour l'instance de S * et * espace pour la boîte. Boxing S utilisera * plus * de temps, car il faut du temps pour mettre en boîte et unbox S. –

+0

Et garder S dans un type de référence ajoutera une pression considérable sur le garbage collector s'il y en a beaucoup. Pouvez-vous expliquer pourquoi vous pensez que c'est une sorte de victoire, parce que cela me semble faire une mauvaise situation - c'est-à-dire, le coût d'une grande structure - loin, bien pire. –

+0

@Eric: Je ne veux pas que la structure devienne trop grande. les structures devraient être petites en utilisation de la mémoire. Il y a d'autres champs dans cette structure et il est déjà sur la limite supérieure. Si T serait un Guid ou un type de valeur encore plus grand, la structure résultante serait trop grande. –

Répondre

2

Si vous essayez d'être absolument sûr que tout type de valeur est encadré, stockez-le dans un champ d'objet et utilisez une propriété pour appliquer la contrainte générique; ie:

struct Example<T> 
{ 
    private object obj; 
    public T Obj 
    { 
     get 
     { 
      return (T)obj; 
     } 
     set 
     { 
      this.obj = value; 
     } 
    } 
} 
+0

Notez cependant, en fonction de la façon dont vous utilisez cette structure, que la mémoire brute de la structure peut différer pour deux valeurs identiques puisque les structs ne sont pas internés et que les boîtes auront des pointeurs différents. la méthode Equals fonctionnera toujours pour la comparaison gérée, ce qui ne concerne que les transitions spécifiques gérées> natives. – TheXenocide

+0

Je pensais que Tuple était un ValueType, mais apparemment ce n'est pas le cas, donc je recommande la réponse de thecoop. – TheXenocide

9

Définir T comme une classe.

struct Foo<T> where T : class 
{ 
    T field; // Now it's a reference type. 
} 
+0

Smart et rapide .. – Dienekes

+0

non, je ne veux pas forcer que T est une classe. Quand T est un type de valeur, je veux qu'il soit stocké comme référence. –

+0

J'ai reformulé la question pour clarifier cela. –

-1

et si vous voulez qu'il soit une instance:

where T : new() 
+1

Ce sera toujours une instance ou une référence null. vous utilisez new() si l'objet de type T a besoin d'être instancié via le constructeur par défaut de type T lors de l'exécution. –

3

Vous pouvez utiliser Tuple<T1> pour tenir votre variable de type valeur (Tuples sont des classes dans la BCL)

struct Foo<T> 
{ 
    Tuple<T> field; 
} 
Questions connexes