En lisant ceci , j’ai appris qu’il était possible de permettre à une méthode d’accepter des parameters de plusieurs types en en faisant une méthode générique. Dans l’exemple, le code suivant est utilisé avec une contrainte de type pour garantir que “U” est un IEnumerable
.
public T DoSomething(U arg) where U : IEnumerable { return arg.First(); }
J’ai trouvé plus de code permettant d’append plusieurs contraintes de type, telles que:
public void test(ssortingng a, T arg) where T: ParentClass, ChildClass { //do something }
Toutefois, ce code semble appliquer cette arg
doit être à la fois un type de ParentClass
et ChildClass
. Ce que je veux faire, c’est dire que arg pourrait être un type de ParentClass
ou ChildClass
de la manière suivante:
public void test(ssortingng a, T arg) where T: ssortingng OR Exception { //do something }
Votre aide est appréciée comme toujours!
Ce n’est pas possible. Vous pouvez toutefois définir des surcharges pour des types spécifiques:
public void test(ssortingng a, ssortingng arg); public void test(ssortingng a, Exception arg);
Si ceux-ci font partie d’une classe générique, ils seront préférés à la version générique de la méthode.
La réponse de Botz est correcte à 100%, voici une brève explication:
Lorsque vous écrivez une méthode (générique ou non) et que vous déclarez les types de parameters pris en charge, vous définissez un contrat:
Si vous me donnez un object qui sait comment faire l’ensemble des choses que Type T sait faire, je peux délivrer «a»: une valeur de retour du type que je déclare ou «b»: une sorte de comportement qui utilise ce type.
Si vous essayez de lui donner plus d’un type à la fois (en ayant un ou) ou essayez de le faire retourner une valeur qui pourrait être plus d’un type, le contrat devient flou:
Si vous me donnez un object qui sait sauter à la corde ou sait calculer pi au 15ème chiffre, je retournerai soit un object pouvant aller à la pêche, soit peut-être mélanger du béton.
Le problème est que lorsque vous entrez dans la méthode, vous ne savez pas si elle vous a donné un IJumpRope
ou un PiFactory
. De plus, lorsque vous utilisez la méthode (en supposant que vous la comstackz comme par magie), vous ne savez pas vraiment si vous avez un Fisher
ou un AbstractConcreteMixer
. Fondamentalement, cela rend le tout plus déroutant.
La solution à votre problème est l’une des deux possibilités suivantes:
Définissez plus d’une méthode qui définit chaque transformation, comportement ou autre possible. C’est la réponse de Botz. Dans le monde de la programmation, on parle de surcharge de la méthode.
Définissez une classe ou une interface de base qui sait comment faire tout ce dont vous avez besoin pour la méthode et dont une méthode ne prend que ce type. Cela peut impliquer de regrouper une ssortingng
et une Exception
dans une petite classe pour définir la manière dont vous prévoyez de les mapper à l’implémentation, mais tout est alors très clair et facile à lire. Je pourrais venir dans quatre ans et lire votre code et comprendre facilement ce qui se passe.
Ce que vous choisirez dépendra de la complexité des choix 1 et 2 et de son caractère extensible.
Donc, pour votre situation spécifique, je vais imaginer que vous sortez simplement un message ou quelque chose de l’exception:
public interface IHasMessage { ssortingng GetMessage(); } public void test(ssortingng a, IHasMessage arg) { //Use message }
Maintenant, tout ce dont vous avez besoin, ce sont des méthodes qui transforment une ssortingng
et une Exception
en un message IHasMessage. Très facile.
Si ChildClass signifie qu’il est dérivé de ParentClass, vous pouvez simplement écrire ce qui suit pour accepter à la fois ParentClass et ChildClass;
public void test(ssortingng a, T arg) where T: ParentClass { //do something }
D’un autre côté, si vous souhaitez utiliser deux types différents sans relation d’inheritance entre eux, vous devez considérer les types implémentant la même interface;
public interface ICommonInterface { ssortingng SomeCommonProperty { get; set; } } public class AA : ICommonInterface { public ssortingng SomeCommonProperty { get;set; } } public class BB : ICommonInterface { public ssortingng SomeCommonProperty { get; set; } }
alors vous pouvez écrire votre fonction générique en tant que;
public void Test(ssortingng a, T arg) where T : ICommonInterface { //do something }