2012-06-04 26 views
5

Puede alguien explicar por qué no es esto posible (al menos en .Net 2.0):C# genéricos: el uso de clase genérica en la cláusula WHERE de método genérico

public class A<T> 
{ 
    public void Method<U>() where U : T 
    { 
     ... 
    } 
} 

... 

A<K> obj = new A<K>(); 
obj.Method<J>(); 

con K siendo la superclase de J

EDIT

He tratado de simplificar el problema para hacer la pregunta más legible, pero claramente exagero. ¡Lo siento!

Mi problema es un poco más específico, supongo. Este es mi código (basado en this):

public class Container<T> 
{ 
    private static class PerType<U> where U : T 
    { 
     public static U item; 
    } 

    public U Get<U>() where U : T 
    { 
     return PerType<U>.item; 
    } 

    public void Set<U>(U newItem) where U : T 
    { 
     PerType<U>.item = newItem; 
    } 
} 

y estoy recibiendo este error:

Container.cs(13,24): error CS0305: Using the generic type Container<T>.PerType<U>' requires 2' type argument(s)

+4

Es posible en 4.0. No es muy útil, porque no usa el parámetro tipo en la firma, pero definitivamente es posible. – dasblinkenlight

+2

Funciona, incluso en .NET 2.0. –

+0

Tiene toda la razón, he editado la pregunta. Lo siento. – andresp

Respuesta

6

En realidad es posible. Este código se compila y se ejecuta muy bien:

public class A<T> 
{ 
    public void Act<U>() where U : T 
    { 
     Console.Write("a"); 
    } 
} 

static void Main(string[] args) 
{ 
    A<IEnumerable> a = new A<IEnumerable>(); 
    a.Act<List<int>>(); 
} 

Lo que no es posible es el uso de covarianza/contravarianza en los genéricos, como se explica here:

IEnumerable<Derived> d = new List<Derived>(); 
IEnumerable<Base> b = d; 
+0

Tienes razón, he editado la pregunta. Lo siento. – andresp

+0

todavía, compila y funciona (por supuesto U Item permanecerá nulo en todo momento; no proporcionó una forma de inicializar su clase PertTyp/su campo de elemento) – YavgenyP

+0

Consulte mi último comentario a mi pregunta. Se supone que la inicialización se realiza llamando al método Set. obj.Set (jObj) La clase PerType debe ser estática. Lo eliminé durante la depuración. He editado la pregunta para agregar la palabra clave nuevamente. – andresp

2

Funciona para mí (VS 2008).

¿Tiene algún problema con la visibilidad de clase? (clase no pública, espacio de nombres incorrecto)

¿Cuál es el mensaje de error que está recibiendo?


ACTUALIZACIÓN

Dada su implementación de Container<T> Puedo escribir

class A { } 
class B : A { } 

class Test 
{ 
    public void MethodName() 
    { 
     var obj = new Container<A>(); 
     obj.Set(new B()); 
    } 
} 

Esto funciona perfectamente. ¿Estás seguro de que B deriva de A? Tenga en cuenta que, por ejemplo, List<B> NO deriva de List<A> (consulte la respuesta de YavgenyP).


El mensaje de error podría ser una pista, que le dice que existe otra Container<T> en otro espacio de nombres que requiere un segundo argumento tipo para PerType<U, X??? >.

+0

Esto debería ser un comentario en lugar de una respuesta. –

+0

Tienes razón, he editado la pregunta. Lo siento. – andresp

+0

Esto es probablemente un error con el compilador Mono o Unity. He hecho esta misma pregunta en su sistema de preguntas y respuestas. Actualmente no tengo forma de probar esto (lo verificaré mañana en la oficina), pero parece ser un problema con el compilador: http://answers.unity3d.com/questions/262475/c-generics- using-class-generic-in-where-clause-of.html Gracias por su visión. – andresp

Cuestiones relacionadas