8
votes

Lancer de génériques à la sous-classe spécifique

J'ai une classe en tant que tel xxx

où, Twotype est dérivé de iNetype .

maintenant , J'ai cette méthode utilitaire xxx

quelle fonction vérifie évidemment le type de vd , et la création d'un approprié> myClass < / code> type. Le seul problème est que le code ci-dessus ne compile pas, et je ne sais pas pourquoi

L'erreur est

ne peut pas lancer l'expression de t à Twotype


1 commentaires

Quelle erreur est le revenu du compilateur?


9 Réponses :


0
votes

Modifiez votre méthode d'usine: xxx

alors vous n'avez pas besoin du commutateur du tout.


1 commentaires

Pourquoi cela est bullevé? C'est la seulement réponse (sur 7 jusqu'à présent) qui peut compiler.



1
votes

Son ne va pas fonctionner dans .NET 3.5 et ci-dessous - la sous-classe n'est pas de type myClass pour tout T, son seul type myClass . Et les classes génériques ne suivent pas l'héritage de leur type de modèle, par ex. myClass est pas une sous-classe de myClass - Ce sont des classes complètement différentes en C #.

Malheureusement, je ne connais pas une façon raisonnable d'écrire votre méthode d'usine.


2 commentaires

Cast à l'objet en premier, tromper le compilateur en permettant la conversion.


Cela ne fonctionnera pas dans le C # 4 non plus. Nous ajoutons des conversions variantes sur des interfaces génériques et des délégués, mais pas sur les classes.



0
votes

Vous n'avez pas la contrainte pour T sur votre méthity méthode.

public static MyClass<T> Factory<T>(T vd) where T: OneType
{
    // ...
}


2 commentaires

Après avoir lu la réponse au-dessus de la mine (de Grzenio), je me souviens de courir dans le même problème. Je ne pense pas que vous puissiez faire ce que vous essayez de faire. Au moins, pas avant .net 4.0 peut-être?


Nope, c n ° 4 ne rend pas mieux cela. Seules les interfaces et les délégués auront des conversions de covariant, pas des cours.



0
votes

Pouvez-vous retourner le design autour de la conception? Au lieu de créer une méthode d'usine inflexible qui doit connaître toutes les sous-classes de onetype code>, ajoutez une méthode abstraite sur oneType code> qui ressemble à ceci;

public class TwoType: MyClass<TwoType>
{
  public override MyClass<OneType> GetMyClass()
  {
      return new SubClass(this);
  }
}


2 commentaires

Le problème est que j'ai besoin de créer le myClass selon * Type transmis.


(publié édité pour donner l'exemple.) Tenez-vous maintenant. Vous n'avez pas de type myclass. Vous avez un nombre sans fin type - MyClass , MyClass , etc. Mais ce sont des types totalement différents. Vous ne pouvez utiliser utilement MyClass



0
votes

Cela devrait fonctionner:

return (MyClass<T>)(object)new SubClass((TwoType)(object)vd);


3 commentaires

Ça ne marche pas. Le message est ne peut pas convertir le type 'ClassLibrary1.Subclass' en "ClassLibrary1.myclass 'd: \ C # \ Exemple1_9 \ ClassLibrary1 \ cl gribrary1 \ class1.c s


sous-classe n'est pas myClass , c'est pourquoi


Êtes-vous sûr de ne pas manquer que (objet) coule entre nouvelle sous-classe et (myClass ) ?



18
votes

Comme grzenio note correctement, une expression de type T n'est pas convertible au tatype. Le compilateur ne sait pas que l'expression est garantie de type Twotype - qui est garantie par votre relevé "Si", mais le compilateur ne considère pas l'implication de la déclaration IF lors de l'analyse des types. Au contraire, le compilateur suppose que T peut être n'importe quel type satisfaisant la contrainte, y compris ThreeType, un type dérivé d'OneType mais pas de dwotype. Évidemment, il n'y a pas de conversion du ThreeType sur Twotype, et il n'y a donc pas de conversion de T sur TwoType non plus.

Vous pouvez tromper le compilateur à lui permettre en disant «Eh bien, traitez le T comme objet, puis jetez l'objet à Twotype ". Chaque étape du chemin est legal - T est convertible en objet, et il pourrait y avoir une conversion d'objet sur Twotype, de sorte que le compilateur le permet. P>

Vous aurez ensuite le même problème de conversion de la sous-classe à myClass code>. Encore une fois, vous pouvez résoudre le problème en casting à l'objet d'abord. P>

Cependant, ce code est toujours faux: p> xxx pré>

pourquoi est-ce faux? Eh bien, considérons tout ce qui pourrait aller mal ici. Par exemple: vous dites p> xxx pré>

Que se passe-t-il? Nous n'appelons pas le constructeur de sous-classe car l'argument n'est pas exactement de type Twotype, il est d'un type dérivé du double-type. Au lieu d'un commutateur, vous voulez probablement P>

public static MyClass<T> Factory<T>(T vd) 
  where T:OneType 
{ 
  if (vd is TwoType && typeof(T) == typeof(TwoType))
       return (MyClass<T>)(object)(new SubClass((TwoType)(object)vd)); 
  // snip for other type check 
} 


0 commentaires

0
votes

Ceci fonctionne pour moi: xxx

dans mon formulaire, j'ai eu ceci: xxx

édition: évidemment ce n'est pas idéal comme Eric souligne ci-dessus. Alors que ce code compile techniquement et fonctionne dans une certaine mesure, vous pouvez trouver une meilleure solution globale.


0 commentaires

1
votes

incroyable, je l'ai utilisé en écrivant le code comme tel: xxx

ou xxx

mais, < Pré> xxx

ne fonctionne pas.

Il semble y avoir une différence dans comme et () casting.


0 commentaires

1
votes

Je sais que c'est une vieille question, mais je pense que cela mérite également une réponse à pourquoi em> cela est impossible (sans utiliser divers travaux de contournement laids).

Lorsque vous utilisez des génériques, vous êtes , dans un sens, travailler avec le code de modèle. Le compilateur utilise un ensemble plus strict de règles pour votre code, car il doit également être compiler au moment de l'exécution, où la version finale est compilée. P>

Ainsi, lorsque vous créez des cours ou des méthodes avec des génériques, ils doivent être compiler pour toutes les combinaisons éventuelles forte> qui respecte les restrictions que vous avez définies avec vos contraintes sur les paramètres génériques. P>

J'ai donc simplifié votre code encore pour vous montrer ce qui se passe:

Je déclare d'abord 3 classes. Une classe mère et deux enfants: p> xxx pré>

i puis déclarent une méthode générique où j'essaie de tester le type, puis de vous lancer sur le type enfant: P>

public void InvalidMethod(Sister input)
{
  Child castedReference = null;
  // Following 'if' is never true
  if (input is Child)
  {
    // Following statement is invalid C#
    castedReference = (Child)input;
  }
  // Do stuff...
}


0 commentaires