2010-06-15 64 views
15

Il semble que C# ne supporte pas les templates de type C++. Par exempleFonction de modèle en C# - Type de retour?

template <class myType> 
myType GetMax (myType a, myType b) { 
return (a>b?a:b); 
} 

Je veux que ma fonction ait un type de retour basé sur ses paramètres, comment puis-je l'obtenir en C#? Comment utiliser les modèles en C#

EDIT: Puis-je utiliser object et getType dans le même but?

+0

Je ne vois pas comment vous utilisez GetType pour accomplir la même chose, non. Et vous ne voulez pas qu'une API retourne un objet, à moins que vous ne soyez content que l'appelant ait à lancer partout. –

Répondre

31

Le plus proche de C++ modèles en C# est générique - mais ils ne sont pas très près. En particulier, vous ne pouvez pas utiliser d'opérateurs comme > entre des valeurs de type générique, car le compilateur ne les connaît pas (et vous ne pouvez pas contraindre les types en fonction des opérateurs). D'autre part, vous pouvez écrire:

public T GetMax<T>(T lhs, T rhs) 
{ 
    return Comparer<T>.Default.Compare(lhs, rhs) > 0 ? lhs : rhs; 
} 

ou

public T GetMax<T>(T lhs, T rhs) where T : IComparable<T> 
{ 
    return lhs.CompareTo(rhs) > 0 ? lhs : rhs; 
} 

Notez que la première est nul en toute sécurité; la seconde ne l'est pas.

Une description complète des génériques est bien au-delà de la portée d'une réponse de dépassement de pile; MSDN a quelques informations, ou consultez votre livre C# préféré.

+1

J'ai entendu C# en profondeur a quelques bonnes explications de génériques :) – SWeko

+1

La fonction que j'ai donnée était juste un échantillon, Qu'en est-il des fonctions autres que la comparaison? – SMUsamaShah

+0

@ Life2HO: Eh bien, quelle fonction voulez-vous? Est-ce une méthode d'instance qui est spécifiée dans une interface? Si oui, vous allez bien. –

0

Génériques!

class MyClass<T> where T : IEnumerable (any parent class here!) 
{ 
    T myGeneric {get; set;} 
} 
1

Vous voulez jeter un coup d'œil à generics. Syntaxe:

public T GetMax<T>(T a, T b) { 
    return (a>b?a:b); 
} 

MISE À JOUR à cause de certains commentaires ... Je voulais juste donner un aperçu très rapide. Ouais je suppose qu'il ne compile pas ou ne s'exécute pas correctement. Mais c'est l'idée de base à quoi cela ressemblerait. Vous trouverez des réponses plus complètes sur ce sujet - en attendant.

exécution Syntaxe:

int a = 5; 
int b = 10; 
int result = GetMax(a, b); 

Hope this helps,

Cordialement, Thomas

+0

J'étais sur le point de dire la même chose mais ça ne compilera pas à cause de la ligne 'return (a> b? A: b);' Il aura besoin d'une contrainte d'interface ou de quelque chose ... –

+1

Vous ne pouvez pas comparer a et b de cette façon, car le compilateur n'a aucune idée de ce qu'est T. Que faire si le type T ne supporte pas la comparaison? –

2

Votre code serait quelque chose comme ceci:

public T GetMax<T>(T a, T b) where T : IComparable<T> 
{ 
    return a.CompareTo(b) > 0 ? a : b; 
} 
6

Generics en C# ne sont pas aussi puissants que les modèles en C++. Ce que vous voulez faire ne fonctionne pas en C#.

Un hack/solution pour votre situation est

public T GetMax<T>(T a, T b) where T: IComparable { 
    if(a.CompareTo(b) > 0) { 
     return a; 
    } 
    return b; 
} 
+0

La fonction que j'ai donnée était juste un échantillon, Qu'en est-il des fonctions autres que la comparaison? – SMUsamaShah

+1

@ LifeH2O: Cela dépend - est-il spécifié dans une interface? Si c'est le cas, vous pouvez contraindre le type générique à implémenter l'interface (ou dériver d'une classe de base donnée, etc.). –

+1

En tant que développeur C++, vous pouvez être déçu par les génériques C#. Mais ils sont encore utiles dans de nombreux scénarios et méritent d'être étudiés. –

0

Vous voulez dire quelque chose comme ça

public static IEnumerable<TResult> SelectIfNotNull<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) 
    { 
     if (source == null) return null; 
     return source.Select(selector); 
    }