Je pense que je connais la réponse à cela, mais j'ai la nécessité de préciser qu'une méthode générique peut prendre un type basé sur deux contraintes facultatives. Qu'être que t peut être soit un type, soit un autre.
public WebPage Click<T>(Func<WebPage> predicate) where T : LinkBase || FieldBase, new()
{
WebDriver.FindElement(new T().LinkPath).Click();
WebDriver.Wait();
return predicate.Invoke();
}
3 Réponses :
Faire cela n'a pas de sens si Je dites que cela n'a pas de sens, car la raison même d'utiliser les contraintes de type consiste à s'assurer que le paramètre de type générique utilisé prend en charge une interface publique connue (sinon, vous pourriez avoir tout simplement fait la chose à être non rendue. -Géné et utiliser linkbase code> et fieldbase code> ne possède pas de base courante ni implémenter une interface commune. Et s'ils le font, vous pouvez simplement utiliser celui-là comme contrainte. P>
objet code>). Mais si vous avez une contrainte hypothétique "ou", comment le compilateur serait-il en mesure de s'assurer que le code que vous écrivez à l'intérieur du générique sera efficace pour le paramètre de type qui finit par être spécifié? P>
Selon la réponse à Mike, cela peut poser une question sur la conception. Ils n'ont pas de base commune entre eux, mais la méthode exige qu'elle ait la même propriété. Le compilateur est donc / pouvait savoir que la propriété existe / peut exister. Oui, je pourrais passer le linkpath dans, mais je ne veux pas.
@Ryan - Si Tout i> vous avez besoin est le linkpath, alors vous Devrait-être i> considérer que de ne pas passer cela. Le principe du moins de connaissances serait applicable.
@RyantomLinson: Nature dynamique des génériques (par opposition aux modèles C ++, où le compilateur fera exactement ce que vous suggérez) signifie que le compilateur doit générer du code qui fonctionne comme dans les deux cas. Comme vous le savez probablement déjà, en C # votre seule option pour le faire est la réflexion. Mais la réflexion perd la sécurité des types pendant que les génériques sont destinés à offrir une sécurité de type. Ce n'est donc pas une option d'émettre le code d'émetteur compilateur qui reflète sur les objets (il aurait également d'autres inconvénients majeurs). Cela ne laisse pas de solution réalisable.
@RyantomLinson: Cependant, vous pouvez simplement utiliser vos classes implémenter la même interface et exposer linkpath code> via cette interface. Ce serait-il une solution de contournement satisfaisante?
@Jon - Oui c'est ce que j'ai actuellement parti. Je comprends que le compilateur doit connaître le type de contraintes génériques et de réflexion n'est pas exactement ce que je voulais dire. Comme je l'ai dit, je suis sûr que ce serait impossible pour la langue d'être capable, mais je voulais juste être sûr.
@Tonthony - Le problème avec c'est que, par conception, je ne veux que le champ ou la base de liaison à connaître son linkpath. Cela ne devrait pas être transmis à la méthode, car seuls les objets eux-mêmes devraient tenir cette connaissance.
@Ryan, considérez vos mots que vos mots signifient. Si la méthode est même consciente de .LinkPath code>? Cette propriété devrait-elle même faire partie de l'API publique? Par votre code, vous voulez clairement que les connaissances soient partagées. C'est juste une question de quand vous choisissez de en profiter.
Toutes mes excuses, par "transmission à la méthode", je voulais dire passer directement sous forme de chaîne. Je veux que cela soit autonome dans un objet de lien où d'autres propriétés et méthodes existent sur cet élément de page.
Vous avez raison, il n'y a aucun moyen de passer de multiples types dans une méthode générique. P>
Avez-vous un contrôle sur les deux types? Pouvez-vous les faire appliquer chaque interface ou une même classe abstraite? P>
C'est correct. Essentiellement, ils ont tous deux une propriété LinkPath et il est douteux que cela puisse partager cette abstraction. Cependant, la question en général est toujours debout où ce n'est pas le cas.
Bien sûr, je crois comprendre que l'abstraction peut être discutable, mais si c'est juste la propriété d'une seule propriété, alors une interface ici devrait faire le tour, et c'est bien par les pratiques de conception. Sinon, il n'y a pas de moyen pour une méthode générique de prendre plusieurs types, car le compilateur doit savoir exactement quelles propriétés pourraient être transmises, et il ne peut pas simplement en déduire que deux types différents ont la même propriété commune.
Une option pour de tels problèmes est d'appliquer le motif de l'adaptateur à vos classes. Dans ce cas, ils partagent les mêmes propriétés, mais pas la même interface. (Ceci est très utile si vous ne contrôlez pas la source ou que cela n'a pas de sens pour eux de partager une interface dans des scénarios normaux.)
interface ILinkablePath
{
string LinkPath { get; }
}
class LinkBaseAdapter : ILinkablePath
{
private LinkBase linkBase;
public LinkBaseAdapter(LinkBase linkBase)
{
this.linkBase = linkBase;
}
public string LinkPath { get { return this.linkBase.LinkPath; } }
}
Oui cela a un sens anthony. Merci.
Quiconque a voté pour fermer, comment sur Terre n'est-ce pas une vraie question?
Remarque: la duplication de la méthode comme vous le suggérez serait également insuffisante. Les contraintes ne font pas partie de la signature, elles devraient donc différer de plus que cela. Le nom, les arguments, etc.; Il doit y avoir une autre variance.