Existe-t-il un moyen de stocker IReturn dans le type de variable IReturn ou pouvez-vous expliquer pourquoi cela ne peut pas être fait?
Disons que j'ai un constructeur de conteneur:
public static ContainerX CreateInstance<T>(IReturn<T> instance)
where T : class, IFeatureX => new ContainerX { Body = instance };
Je veux dire que IFeatureX étend aussi class , je ont essayé de changer le constructeur en privé et d'utiliser:
public ContainerX(IReturn<IFeatureX> body) : this()
{
Body = body;
}
Cependant c # ne sait pas que IReturn IReturn.
Il semble que je ne puisse pas le lancer ou le lancer en toute sécurité.
Je ne peux pas utiliser object ou dynamic car IFeatureX est en fait IProtobufBody et c'est un interface d'étiquette que j'utilise pour faire un test d'intégration garantit que tous les assemblys qui stockent des instances dans le conteneur ont un contrat protobuf défini.
3 Réponses :
Il vous suffit de rendre IReturn covariant en le déclarant comme IReturn . Vous pouvez en savoir plus sur la covariance et la contravariance ici .
Il s'agit d'un problème de covariance et de contravariance ( voir ici ).
Disons que vous avez une classe appelée Dog qui hérite de Animal , considérez le code suivant:
List<Dog> l = new List<Dog>(); List<Animal> la = l; la.Add(new Giraffe()); // this is not allowed
Cet exemple montre pourquoi il n'est pas autorisé par défaut.
Il y a les mots-clés in et out qui vous permettent utilisez la contravariance et la covariance comme IReturn ou IReturn .
Lorsque vous utilisez in , alors vous pouvez stocker un objet IReturn dans une variable de type IReturn et définir des fonctions dans IReturn qui utilisent T comme variable d'entrée Type.
Lorsque vous utilisez out , vous pouvez stocker un objet IReturn dans une variable de type IReturn et définissez les fonctions dans IReturn qui utilisez T comme type de retour.
Si vous avez besoin que T soit un type de variable d'entrée dans certaines fonctions et un type de retour dans d'autres fonctions, alors vous ne peut fonctionner qu'avec la classe exacte.
Désolé, les autres réponses n'étaient pas applicables. Dans ce cas particulier, la réponse était d'avoir
IReturn<T> ... where T : FeatureBase
et d'avoir des instances étendant FeatureBase.
IFeatureX => nouveau ContainerX {Body = instance};est sûrement quelque chose qui est évalué au moment de l'exécution , alors que les génériques sont une fonctionnalité à la compilation . Que feriez-vous exactement avec cette mission? Oubliez simplement lanouvellepartie. Quoi qu'il en soit,IFeatureest un très mauvais nom pour une classe. La plupart des gens interpréteraient le premierIcomme un indicateur d'une interface.@HimBromBeere comme je l'ai mentionné, j'ai remplacé IProtobufBody par IFeature afin qu'il ne détourne pas l'attention, de la même manière que ContainerX est en fait un message RabbitMq stockant une demande de servicestack, une "promesse" de retourner une réponse.