2011-05-29 13 views
7

Estoy tratando de pasar un tipo de delegado como un parámetro de tipo para que pueda usarlo como un parámetro de tipo más adelante en el código, así:Pasar un delegado como un parámetro de tipo y usarlo arroja el error CS0314

// Definition 
private static class Register 
{ 
    public static FunctionObject Create<T>(CSharp.Context c, T func) 
    { 
    return new IronJS.HostFunction<T>(c.Environment, func, null); 
    } 
} 

// Usage 
Register.Create<Func<string, IronJS.CommonObject>>(c, this.Require); 

sin embargo, el compilador de C# se queja:

The type 'T' cannot be used as type parameter 'a' in the generic type or method 
'IronJS.HostFunction<a>'. There is no boxing conversion or type parameter 
conversion from 'T' to 'System.Delegate'." 

he tratado de solucionar este problema añadiendo "donde T: System.Delegate" a la función, sin embargo, no se puede utilizar como System.Delegate una restricción en los parámetros de tipo:

Constraint cannot be special class 'System.Delegate' 

¿Alguien sabe cómo resolver este conflicto?

no funciona (argumento y retorna información de tipo se pierde durante molde):

Delegate d = (Delegate)(object)(T)func; 
return new IronJS.HostFunction<Delegate>(c.Environment, d, null); 
+0

¿Por qué su solución contiene un '(T)'? – Gabe

+0

@Gabe: Fue el tipo que se pasa en Crear . Lamentablemente, la solución propuesta no funciona en tiempo de ejecución. –

+0

¿Puede mostrar el código de la solución propuesta que no funciona y explicar cómo no funciona? – Gabe

Respuesta

6

Si nos fijamos en https://github.com/fholm/IronJS/blob/master/Src/IronJS/Runtime.fs verá:

and [<AllowNullLiteral>] HostFunction<'a when 'a :> Delegate> = 
    inherit FO 
    val mutable Delegate : 'a 

    new (env:Env, delegateFunction, metaData) = 
    { 
     inherit FO(env, metaData, env.Maps.Function) 
     Delegate = delegateFunction 
    } 

En otra palabras, no puede usar C# o VB para escribir su función porque requiere usar System.Delegate como una restricción de tipo. Yo recomiendo ya sea escribiendo su función en C# o el uso de la reflexión, de esta manera:

public static FunctionObject Create<T>(CSharp.Context c, T func) 
{ 
    // return new IronJS.HostFunction<T>(c.Environment, func, null); 
    return (FunctionObject) Activator.CreateInstance(
    typeof(IronJS.Api.HostFunction<>).MakeGenericType(T), 
    c.Environment, func, null); 
} 
+0

'Activator.CreateInstance > (c.Environment, func, null);' debería funcionar también, ¿no? Además, buena captura en la restricción F # :) – leppie

+0

@leppie: Lo mismo que impide que 'new' funcione también evitará que' Activator.CreateInstance' funcione. – Gabe

+0

Ah bien ... .. :) – leppie

0

@Gabe tiene toda la razón, tiene que ver con la restricción de tipo en la HostFunction < 'a> clase que sólo es válido en F # (y no C# o VB).

¿Ha comprobado las funciones en Native.Utils? Es lo que usamos internamente en el tiempo de ejecución para crear funciones de los delegados. Especialmente la función let CreateFunction (env:Env) (length:Nullable<int>) (func:'a when 'a :> Delegate) = debería hacer exactamente lo que necesita.

Si CreateFunction no cumple con lo que necesita, abra un ticket al http://github.com/fholm/IronJS/issues con lo que se está perdiendo y cómo le gustaría que se implemente y lo solucionaremos.

+0

No solo es válido en F #. Es válido en cualquier lenguaje .NET que no tenga intencionalmente lisiado restricciones de tipo restringido. –

Cuestiones relacionadas