2010-04-28 7 views
13

Après avoir défini cette interface:Question sur C# 4.0 de génériques covariance

public interface IInputBoxService<out T> { 
    bool ShowDialog(); 
    T Result { get; } 
} 

Pourquoi le travail de code suivant:

public class StringInputBoxService : IInputBoxService<string> { 
    ... 
} 

... 

IInputBoxService<object> service = new StringInputBoxService(); 

et cela ne ?: pas

public class IntegerInputBoxService : IInputBoxService<int> { 
    ... 
} 

... 

IInputBoxService<object> service = new IntegerInputBoxService(); 

Est-ce que cela a quelque chose à voir avec int étant un type de valeur? Si oui, comment puis-je contourner cette situation?

Merci

+0

Avez-vous essayé d'utiliser Int32 – Strelok

+1

Non, mais d'après ce que je crois comprendre qu'il conduirait au même int est juste un alias pour?. Int32 –

Répondre

14

Oui, il doit absolument faire avec int étant un type de valeur. La variance générique en C# 4 ne fonctionne qu'avec les types de référence. C'est principalement parce que les références ont toujours la même représentation: une référence est juste une référence, ainsi le CLR peut utiliser les mêmes bits pour quelque chose qu'il sait être une référence de chaîne comme pour une référence d'objet. Le CLR peut s'assurer que le code sera sûr, et utiliser le code natif qui ne connaît que IInputBoxService<object> lorsqu'il est passé un IInputBoxService<string> - la valeur retournée par Result sera compatible avec la représentation (si un tel terme existe!).

Avec int =>object il devrait y avoir boxe etc, de sorte que vous ne finissez pas avec le même code - ce qui salit fondamentalement la variance.

EDIT: Le C# 4.0 spec dit ceci dans la section 13.1.3.2:

Le but des annotations de la variance est de prévoir plus clémentes (mais toujours SÛR type) conversions à l'interface et types délégué . A cette fin, les définitions des implicites (§ 6.1) et conversions explicites (§6.2) utilisent de la notion de variance-convertibilité, qui est définie comme suit: Un type T est la variance convertible à un type T si T est soit une interface ou un type délégué déclaré avec les paramètres de type de variante T, et pour chaque type de variante paramètre Xi une de l' suivante est vérifiée:

  • Xi est covariant et un implicite référence ou identité conversion existe de Ai Bi

  • Xi est contravariant et une référence implicite ou conversion identité existe de Bi Ai

  • Xi est invariant et une conversion d'identité existe de Ai Bi

Cela ne fait pas existe terriblement évident, mais essentiellement des conversions de référence seulement être tween reference types, ce qui ne laisse que des conversions d'identité (c.-à-d. d'un type à lui-même).En ce qui concerne les solutions de contournement: Je pense que vous devez créer votre propre classe wrapper, fondamentalement. Cela peut être aussi simple que:

public class Wrapper<T> 
{ 
    public T Value { get; private set; } 
    public Wrapper(T value) 
    { 
     Value = value; 
    } 
} 

Il est assez méchant si :(

+0

Je pensais que c'était le cas, mais je ne trouve pas de référence Connaissez-vous un lien msdn mentionnant que les variances fonctionnent uniquement avec les types de référence? –

+0

Que diriez-vous de celui-ci? Http: //blogs.msdn. com/csharpfaq/archive/2010/02/16/covariance-et-contravariance-faq.aspx - Utilisez Ctrl + F pour trouver "Quelques règles importantes à mémoriser" et vous trouverez l'entrée –

+0

Y at-il une alternative? ? Java définit pour tous types de référence des types primitifs aussi, donc au lieu de faire quelque chose je peux faire quelque chose , ce qui résoudrait ce problème. –

Questions connexes