9
votes

Lancer à plusieurs interfaces

Dupliqué possible:
Casting an Objet à deux interfaces en même temps, d'appeler une méthode générique

Je suis assez sûr que vous ne pouvez pas faire cela, donc je me demande s'il y a une solution de contournement, mais j'ai besoin / vouloir lancer un objet pour représenter plusieurs interfaces à utiliser avec des contraintes génériques. Par exemple: xxx

Si j'ai un objet, je veux dire quelque chose comme var t = (iterfacea | iterfaceb) Toobj; donc je peux passer t dans cette méthode.

Y a-t-il une façon de faire cela? J'utilise c # 3.5 Donc, pas de dynamique disponible, mais si c'est possible avec dynamique, veuillez le poster de toute façon.


16 commentaires

Quel type voulez-vous que ce soit après la distribution?


Vérifiez le concept de covariance de .NET Framework 4, cela peut aider, mais pour cela, vous devez également modifier la mise en œuvre.


Pouvons-nous avoir l'héritage des interfaces?


@CJBREW Eh bien, je suppose que ce sera un type qui n'existe pas, mais réalise les deux interfaces. Semblable à un type anonyme.


@Ramesh Oui, c'est l'autre solution que je pensais, mais pour diverses raisons, je ne voulais pas descendre cet itinéraire (bien que je doive l'avoir probablement!)


@ user751975 J'ai utilisé la variance CO-Contra dans d'autres projets qui utilisent C # 4.0 et je ne crois pas que cela résoudrait ce problème - mais merci pour l'idée


Pouvez-vous élaborer sur le scénario dont vous avez besoin? Je ne peux pas penser à un seul cas, vous en auriez besoin ...


@Daniel je veux appeler FOO si mon objet réalise les interfaces et la barre si elle réalise différentes interfaces. Le type que j'ai n'est pas suffisamment spécifique (disons son type objet ) afin que je dois jeter avec les deux interfaces afin que je puisse transmettre mon objet dans la méthode.


Dupliquer défini! Je n'ai pas vu cela dans la liste des questions similaires que je saisis la question. Bonne trouvaille, merci


Vous ne pouvez pas avoir un article qui est un poisson et une chaise simultanément.


@Lukas je ne vois pas comment ce commentaire ajoute à la discussion


@Lukas: Que voulez-vous dire avec votre commentaire?


@Richk: Veuillez consulter ma réponse mise à jour.


S'il n'y a pas de relation entre ces deux interfaces, iterfacea, iterfaceb vous ne pouvez pas faire ce que vous voulez. Qu'en souciez-vous du comportement de ces deux objets exprimés par des interfaces. Vous avez un problème d'interfaces ou de votre méthode est trop coupé (ne peut pas dire lequel avec ce minuscule extrait abstrait). Semblable, vous avez deux animaux domestiques, disons un poisson et un chien et vous voulez nourrir l'un d'entre eux, vous pouvez regarder leur comportement - les deux peuvent manger - ou le fait qu'ils soient des mammifères et qu'un mammifère peut manger.


@Lukas il y a une relation. Prenons votre exemple, j'ai deux interfaces, ibreathable et aménagée. Les deux chiens et les poissons réalisent ces deux interfaces et respirent à la fois et bougent de différentes manières. J'ai une méthode qui nécessite quelque chose qui est à la fois - disons qu'il est nécessaire d'appeler respirer chaque fois que nous bougeons, nous ne sortons pas de respiration et mourons. J'ai besoin de couler sur les deux types, mais pas spécifiquement de poisson et non spécifiquement chien car j'ai beaucoup d'animaux dans ma ferme.


@Richk "dis dire qu'il est nécessaire d'appeler respirer chaque fois que nous bougeons" C'est un comportement, définissez une nouvelle intégration (avec héritage) qui décrit le comportement souhaité. Il gardera la chose plus explicite et imo simple.


5 Réponses :


2
votes

Non, il n'y a pas de moyen.
La seule chose qui se rapproche est de créer une autre interface le hérité de ces deux interfaces. Mais alors toutes vos classes doivent mettre en œuvre cette troisième interface au lieu des deux autres, donc dans la plupart des cas, ce n'est pas pratique.

Je viens de le jeter à cette interface dont vous avez besoin à ce moment-là.

Mise à jour:

La seule façon de voir est de créer une classe de conteneurs qui implémente ces interfaces: xxx


3 commentaires

La classe de conteneurs ne fonctionnera pas si vous avez une instance d'une classe qui implémente les deux interfaces mais n'hérite pas de la classe de conteneurs. En d'autres termes, par exemple, System.String implémente à la fois icomparable et ienumerable . Si vous créez Classe X: Icomparable , iEnumerable , vous ne pourrez pas attribuer des chaînes aux variables de ce type, ni inversement.


@Phoog: Je ne suis pas suivi. Vous ne voulez pas affecter la chaîne à x mais transmettez-la dans le constructeur ...


Aha je vois. Désolé, je lisais trop vite et je n'ai pas compris l'approche que vous suggérez.



3
votes
IInterfaceA tA = (IInterfaceA)someObj;
IInterfaceB tB = (IInterfaceB)someObj;

3 commentaires

Désolé je pense que ma question a été mal libérée, je ne veux pas faire le casting dans la méthode, je veux faire l'extérieur pour que je puisse le transmettre dans la méthode


Vous n'avez pas à couler pour appeler. Utilisez simplement n'importe quel type qui implémente les deux.


Oui, la chose est au point où j'appelle FOO, je ne sais pas à la compilation, quel est le type, je ne peux pas le jeter à un type défini car il existe plusieurs classes qui réalisent les deux interfaces



1
votes

Un moyen possible de le faire est d'héritage d'interfaces. Déplacez la fonctionnalité commune à l'interface parente, qui doit être utilisée dans des scénarios ci-dessus.


0 commentaires

0
votes

Vous pourrez peut-être restructurer votre héritage pour atteindre votre objectif.

public class ArrayList : IList, ICollection, IEnumerable, ICloneable
public interface IList : ICollection, IEnumerable


0 commentaires

3
votes

Edit

Malgré la réponse ci-dessous, je dirais que la meilleure solution est celle que la plupart des autres réponses pointaient. (Cela suppose que vous pouvez redéfinir les multiples classes qui implémentent les interfaces.) P>

Créer une interface qui hérite à partir de l'interfacea et d'interfaceb, puis pour toutes les classes qui implémentent des interfaces A et B, remplacez ces interfaces avec le nouveau. Avant: p> xxx pré>

après: p> xxx pré>

La mise en œuvre de FOO est alors assez triviale. Et, encore une fois, puisque vous ne savez pas à la compilation, quel type vous avez sur la main, vous pourrez peut-être simplement le déclarer comme p> xxx pré>

fin d'exécution p>


Vous pouvez le faire en utilisant la réflexion, même si certains diront que ce n'est pas particulièrement "Nifty": P>

private void PrivateFoo(IInterfaceA objA, IInterfaceB objB)
{
    if (!ReferenceEquals(objA, objB))
        throw new ArgumentException("objA and objB must refer to the same object");

    //... do your thing here
}
public void Foo(object someObj)
{
    PrivateFoo((IInterfaceA)someObj, (IInterfaceB)someObj);
}


0 commentaires