web-dev-qa-db-fra.com

Méthode générique où T est type1 ou type2

Existe-t-il un moyen de déclarer une fonction générique que le type générique est de type1 ou type2?

exemple:

public void Foo<T>(T number)
{
}

Puis-je contraindre T à être int ou long 

23
gdoron

Bien que vous puissiez utiliser un generic contrainte pour limiter le type de chaque argument générique T, aucun ne vous permet malheureusement de faire appliquer au moment de la compilation si T est type1 or type2

Il n’existe pas non plus de moyen de faire en sorte, au moment de la compilation, que votre argument générique ne puisse être que de type primitif (int, long, double, ...).

14
Darin Dimitrov

Pour les objets ReferenceType, vous pouvez faire

public void DoIt<T>(T someParameter) where T : IMyType
{

}

...

public interface IMyType
{
}

public class Type1 : IMyType
{
}

public class Type2 : IMyType
{
}

Pour votre cas, utiliser le paramètre long as limitera l'utilisation à long et à long de toute façon.

public void DoIt(long someParameter)
{

}

pour contraindre à n’importe quel type de valeur (comme: int, double, court, décimal), vous pouvez utiliser:

public void DoIt<T>(T someParameter) where T : struct
{

}

pour plus d'informations, vous pouvez consulter la documentation officielle ici

14
Adam Moszczyński

Non.

Cela n'a pas de sens. T n'aurait pas de type utilisable à la compilation dans la méthode.

Au lieu de cela, vous devez créer deux méthodes surchargées.

7
SLaks

Utilisez plutôt des méthodes surchargées:

public void Foo(int number)
{
} 

public void Foo(long number)
{
}

De toute façon, vous ne pouvez pas effectuer d’opérations arithmétiques sur des types génériques. Notez que vous pouvez transmettre une valeur int à un paramètre long. Il sera automatiquement converti en long. Avoir une seule méthode avec un paramètre long pourrait donc suffire.

Les anciens langages de programmation fonctionnaient après le principe "Il ne peut y avoir qu'un seul". C # vous permet d'avoir plusieurs méthodes avec le même nom dans la même classe, interface ou structure. Ces méthodes doivent avoir une signature différente. Cela signifie qu'ils doivent avoir un nombre différent de paramètres ou des paramètres de types différents (ou les deux). C'est ce qu'on appelle la surcharge de méthode.

5

Je sais que c’est une vieille question, et que cela n’y répond pas parfaitement, mais vous pouvez le faire avec une seule méthode, plutôt que de créer des multiples ou en utilisant des contraintes génériques ... particulièrement utile si vous avez 20 types impairs à vérifier.

Évidemment, la vérification du type de compilateur n’est pas identique à celle que vous faites lorsque vous utilisez une contrainte, mais cela peut aider dans certaines circonstances ...

public void MyMethod<T>()
{
    if (!typeof(T).Equals(typeof(int)) &&
        !typeof(T).Equals(typeof(long)))
            throw new Exception("T must be int or long");

    //your logic here
}
0
Detail

Je ne pense pas que ce soit actuellement possible. 

Cette question sur la création d’une bibliothèque de mathématiques couvre en quelque sorte le même terrain et inclut des solutions de contournement.

0
Jon Egerton

J'ai également eu ce problème et je pense avoir trouvé une meilleure solution (en supposant qu'une version surchargée de votre méthode est insuffisante):

Mélanger Type1 et Type2 sans aucun parallèle n'a aucun sens, comme cela a déjà été écrit. Il doit donc y avoir une méthode ou une propriété accessible pour les deux types d'objet. Pour vous assurer que le compilateur dispose de ces méthodes ou propriétés pour votre objet, regroupez Type1 et Type2 en créant une interface MyInterface et en l'implémentant par Type1 et Type2:

interface MyInterface {
  void MyCommonMethod();
  bool MyCommonProperty { get; }
}

class Type1 : MyInterface {
  void MyCommonMethod() {
    // TODO: Implement it for Type1
  }

  bool MyCommonProperty {
  get {
    // TODO: Implement it for Type1
  }
  }
}

class Type2 : MyInterface {
  void MyCommonMethod() {
    // TODO: Implement it for Type2
  }

  bool MyCommonProperty {
  get {
    // TODO: Implement it for Type2
  }
  }
}

Maintenant, pour réécrire votre méthode Foo afin d’accepter Type1 et Type2, la contrainte T sera un objet MyInterface:

public void Foo<T>(T number) where T : MyInterface
{
  throw new NotImplementedException();
}

Je me morfondre cela pourrait être utile. :)

0
KnorxThieus