2011-04-28 22 views
9

Hola
tengo este código usando genérico y anulable:parámetro de tipo genérico y la sobrecarga del método anulable

// The first one is for class 
public static TResult With<TInput, TResult>(this TInput o, 
      Func<TInput, TResult> evaluator) 
    where TResult : class 
    where TInput : class 

// The second one is for struct (Nullable) 
public static TResult With<TInput, TResult>(this Nullable<TInput> o, 
      Func<TInput, TResult> evaluator) 
    where TResult : class 
    where TInput : struct 

Tenga en cuenta la restricción TInput, una es la clase, el otro es struct. Luego los uso en:

string s; 
int? i; 

// ... 

s.With(o => ""); 
i.With(o => ""); // Ambiguos method 

Causa un error de Ambiguos. Pero también tengo el otro par:

public static TResult Return<TInput, TResult>(this TInput o, 
      Func<TInput, TResult> evaluator, TResult failureValue) 
    where TInput : class 

public static TResult Return<TInput, TResult>(this Nullable<TInput> o, 
      Func<TInput, TResult> evaluator, TResult failureValue) 
    where TInput : struct 

Ésta se compila correctamente

string s; 
int? i; 

// ... 

s.Return(o => 1, 0); 
i.Return(o => i + 1, 0); 

me dieron ninguna pista qué esto suceda. El primero parece correcto, pero compila el error. El segundo ('Retorno') debería ser un error si el primero es, pero se compila con éxito. ¿Me he perdido algo?

+0

Al igual que un comentario de estilo, evitaría usar el mismo nombre para un parámetro lambda que para una variable que ya está en el alcance. –

+0

ah bien, que en realidad causa un error de compilación. Simplemente pego y edito el código apresuradamente. –

Respuesta

10

limitaciones del método genérico no se consideran mientras que la elección de una sobrecarga - son revisados ​​después de la sobrecarga ha sido elegido.

Restricciones dentro de los tipos de los parámetros son marcados como parte de la elección de una sobrecarga. Es un poco confuso, pero finalmente tiene sentido.

Tengo un blog post en esto que puede ayudar a entenderlo más.

Además tenga en cuenta que su segundo ejemplo tiene el argumento adicional que contribuye a la inferencia de tipo, que es lo que hace la diferencia entre los dos. TResult se infiere a ser int, que impide que el primero de sobrecarga de ser válido - no hay conversión (int? x) => x + 1-Func<int?, int> mientras que no es una conversión (int x) => x + 1-Func<int, int>.

+0

Estoy bastante consumido ahora, y estoy tratando de entender tu último párrafo. Los dos delegados Func <> no usan nullable (int?) En absoluto. Solo los primeros parámetros son. –

+0

@Hendry: la primera sobrecarga en cada caso tratará 'TInput = int?' Porque lo está llamando en un 'int?'. El tipo de parámetro 'evaluator' sería, por lo tanto,' Func '. –

+0

oh veo, es por eso que la resolución de sobrecarga, basada en la función lambda, falla en la primera 'Devolución' y fluye a la segunda. Muchas gracias. –

Cuestiones relacionadas