2010-06-15 17 views
15

Parece que C# no admite plantillas similares a C++. Por ejemploFunción de plantilla en C# - Tipo de devolución?

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

Quiero que mi función tenga un tipo de devolución basado en sus parámetros, ¿cómo puedo lograr esto en C#? Cómo usar plantillas en C#

EDITAR: ¿Puedo usar object y getType para casi el mismo propósito?

+0

no veo la forma en que tendría que utilizar GetType a lograr lo mismo, no. Y no quiere un objeto que regrese la API a menos que esté contento de que la persona que llama tenga que emitir por todas partes. –

Respuesta

31

El más cercano a las plantillas de C++ en C# es genéricos - pero no son muy cerca. En particular, no puede usar operadores como > entre valores de tipo genérico, porque el compilador no los conoce (y no puede restringir tipos basados ​​en operadores). Por otro lado, se puede escribir:

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

o

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

Tenga en cuenta que el primero de ellos es nula de fallos; el segundo no es

Una descripción completa de genéricos está más allá del alcance de una respuesta de desbordamiento de pila; MSDN tiene alguna información, o consulte su libro favorito de C#.

+1

He escuchado que C# en profundidad tiene algunas buenas explicaciones de los genéricos :) – SWeko

+1

La función que he dado es solo una muestra, ¿qué pasa con las funciones que no sean de comparación? – SMUsamaShah

+0

@ Life2HO: Bueno, ¿qué función quieres? ¿Es un método de instancia que se especifica en una interfaz? Si es así, estás bien. –

0

Genéricos!

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

Querrá echar un vistazo a generics. Sintaxis:

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

ACTUALIZACIÓN debido a algunos comentarios ... Sólo quería dar una visión muy rápida. Sí, supongo que no compila o no se ejecuta correctamente. Pero esta es la idea básica de cómo se vería esto. Encontrarás respuestas más completas sobre este tema, mientras tanto.

ejecución Sintaxis:

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

Espero que esto ayude,

Saludos, Thomas

+0

Estaba a punto de decir lo mismo, pero eso no se compilará debido a la línea 'return (a> b? A: b);' Necesitará una restricción de interfaz o algo ... –

+1

No se puede comparar ayb de esta manera, ya que el compilador no tiene idea de qué es T. ¿Qué sucede si el tipo T no es compatible con la comparación? –

2

Su código se convertiría en algo como esto:

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

genéricos en C# no son tan potentes como plantillas en C++. Lo que quieres hacer no funciona en C#.

un hack/solución para su situación es

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

La función que di fue solo una muestra, ¿qué pasa con las funciones que no sean de comparación? – SMUsamaShah

+1

@ LifeH2O: depende - ¿está especificado en una interfaz? Si es así, puede restringir el tipo genérico para implementar la interfaz (o derivar de una clase base dada, etc.). –

+1

Como desarrollador de C++, puede sentirse decepcionado con los genéricos de C#. Pero todavía son útiles en muchos escenarios, y vale la pena aprender. –

0

¿Quieres decir algo como esto

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