2011-02-08 11 views
15

Estoy trabajando con una plataforma .NET plataforma específica, que está precompilada y no OpenSource. Para algunas tareas, necesito extender esta clase, pero no heredando de ella. Simplemente quiero agregar un método.¿Cómo escribo un método de extensión para un tipo genérico con restricciones en los parámetros de tipo?

Al principio yo quiero mostrar una clase existente dummycode:

public class Matrix<T> where T : new() { 
    ... 
    public T values[,]; 
    ... 
} 

quiero extender esta clase de la siguiente manera:

public static class MatrixExtension { 
    public static T getCalcResult<T>(this Matrix<T> mat) { 
     T result = 0; 
     ... 
     return result; 
    } 
} 

Tengo esta sintaxis de muchos google enlaces así que no tengo idea si es correcto. El compilador no me dice ningún error, pero al final no funciona. Al final quiero llamar a esta función de la siguiente manera:

Matrix<int> m = new Matrix<int>(); 
... 
int aNumber = m.getCalcResult(); 

Así Alguien tiene una idea? ¡Gracias por tu ayuda!

Saludos Nem

+0

¿Por qué cree que no funciona? ¿Lanza una excepción? –

+1

Esta es la forma correcta de usar un método de extensión, pero en lugar de 'T result = 0' debe tener' T result = default (T) 'porque T no está inicialmente limitado a' int'.Aparte de eso, debe verificar que tenga la instrucción de uso para incluir su clase MatrixExtension. Siempre puede verificar llamando a 'MatrixExtension.getCalcResult (m)' directamente para ver si está funcionando. –

+0

Al menos el IDE me obliga a llamar al método de esta manera: m.getCalcResult (); Pero cuando intento compilar este consigo otro error: > 'Matrix ' no contiene una definición para 'GetValue' y ningún método de extensión 'GetValue' aceptar un primer argumento de tipo 'Matrix ' podría ser encontrado (¿falta una directiva de uso o una referencia de ensamblado?) Por cierto, esta forma de llamar al método no tiene sentido porque el Parámetro T genérico ya está asignado. –

Respuesta

23

Debe agregar las mismas restricciones de parámetros de tipo en el método de extensión.

Este es mi intento de la reconstrucción más cerca de su ejemplo que compila y ejecuta, sin ningún tipo de error:

public class Matrix<T> where T : new() { 
    public T[,] values; 
} 


public static class MatrixExtension { 
    public static T getCalcResult<T>(this Matrix<T> mat) where T : new() { 
     T result = new T(); 
     return result; 
    } 
} 

class Program { 
    static void Main(string[] args) { 
     Matrix<int> m = new Matrix<int>(); 
     int aNumber = m.getCalcResult(); 
     Console.WriteLine(aNumber); //outputs "0" 
} 
+0

Estuve pensando en publicar mi código, pero es exactamente lo mismo. – Marlon

+0

Puedes copiar/pegar _mi_ código en un nuevo proyecto para ver qué pasa. –

+0

¡Sí, funciona! ¡Pero ahora sé lo que no he visto! 'clase Matrix donde T: new()' No he mirado eso totalmente. :( –

-2

¿Usted ha mirado en "decoradores" ...

Sample showing Decorator patterns

Un decorador le permite crear una clase con sus propias propiedades y métodos sin hacer una derivación directa de una clase específica Luego, puede "aplicarlo" a CUALQUIER OTRO objeto. Luego puede aplicar usar sus métodos adicionales o propiedades con las que está tratando de trabajar.

Esta muestra fue una búsqueda rápida simple que muestra un ejemplo uniéndose a "coches" mediante la construcción de "opciones" ...

+1

Esa no es realmente una respuesta a su pregunta. –

+0

@Jim Schubert, sí ... Lo sé ... mientras estaba tratando de buscar algunas muestras, la pantalla táctil del mouse debe haber sido golpeada ... hasta que volví a ajustar ... – DRapp

+0

No bajé vote, pero quería decir ... esos envíos de touchpad me atrapan todo el tiempo. Además, +1 porque un decorador podría resolver el problema y es una respuesta viable. Mi primer comentario fue dirigido a cómo una pregunta de una sola oración es más adecuada para un comentario que una respuesta: \ –

2

En este momento, el único "error" que vería es la siguiente:

T result = 0; 

se podría cambiar eso a:

T result = default(T); 

En el caso de los tipos de valor, esto será cero, por lo que sería seguro.

Sin embargo, descubrirá que esto es difícil cuando llega a la sección "..." que ha enumerado. Los tipos básicos (int, double, etc.) no implementan un método que pueda usar para calcular sus cálculos matemáticos. Este es un long time, very highly voted request on Connect, por cierto.

Si bien hay soluciones, hacen la vida muy difícil. A diferencia de las plantillas en C++, los genéricos de C# no son compatibles con las operaciones matemáticas seguras en tipos arbitrarios.

+0

Creo que este es mi problema, que se mantendrá. Pero esa no era mi pregunta. Mi pregunta es cómo extender esta clase genérica. Para una clase no genérica no es problema. –

+0

@nemcija: Sí, pero extender la clase genérica es exactamente como lo hiciste, eso no es un problema. Esto es con lo que te vas a encontrar cuando obtengas el error del compilador corregido. –

Cuestiones relacionadas