2011-11-23 16 views
21

El siguiente código F # declara clases base y descendientes. La clase base tiene un método virtual 'Prueba' con una implementación predeterminada. La clase descendiente anula el método de la clase base y también agrega un nuevo método "Test" sobrecargado. Este código compila bien y no presenta problemas al acceder a cualquiera de los métodos descendientes de 'Prueba'.No se puede resolver un método F # que ha sido anulado y sobrecargado desde C#

F # Código:

module OverrideTest 
    [<AbstractClass>] 
    type Base() = 
    abstract member Test : int -> int 
    default this.Test x = x + 1 

    type Descendant() = 
    inherit Base() 
    override this.Test x = x - 1 
    member this.Test (x, y) = x - y 

Sin embargo, intentar invocar anulación del descendiente de 'prueba' de C# da como resultado un error de compilación:

var result = td.Test(3); <- No overload for method 'Test' takes 1 arguments

El total de C# Código:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Client 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     var td = new OverrideTest.Descendant(); 
     var result = td.Test(3); 
     Console.WriteLine(result); 
     Console.ReadKey(); 
    } 
    } 
} 

Lo extraño es que Intellisense de VisualStudio ve las dos funciones sobrecargadas y proporciona s firmas correctas para ambos. No da advertencias o errores antes de que la construcción falle, y solo resalta la línea después.

He vuelto a implementar este escenario completamente en C# y no tuve el mismo problema.

¿Alguien tiene alguna idea de lo que está pasando aquí?

+0

¿Ha comparado el IL emitido en ambos idiomas? – Oded

+0

¿Qué sucede si en el código C# subiste a la clase base antes de llamar al método? – Brian

+0

@Brian: Eso funciona. – Daniel

Respuesta

17

hay duda de que está consciente de que si se omite el miembro de Test(x,y) del tipo Descendant - o simplemente cambiarle el nombre Test2(x,y) - a continuación, el código C# será compilar y ejecutar como se esperaba.

En cuanto a la IL generada para su tipo original Descendant ofrece una pista:

.method public hidebysig virtual 
    instance int32 Test (
     int32 x 
    ) cil managed ... 

.method public 
    instance int32 Test (
     int32 x, 
     int32 y 
    ) cil managed ... 

en cuenta que no hay hidebysig atributo del método Test(x,y).

El ECMA CLI specification tiene la siguiente información acerca de hidebysig. (Sección 15.4.2.2, el énfasis en negrita es mía.)

hidebysig is supplied for the use of tools and is ignored by the VES. It specifies that the declared method hides all methods of the base class types that have a matching method signature; when omitted, the method should hide all methods of the same name, regardless of the signature.

Así, el F # compilador omite el atributo hidebysig, lo que significa que el método Test(x,y) oculta todos los otros métodos llamados Test. Aunque hidebysig es solo "para el uso de herramientas", ¡parece que el compilador de C# es una de esas herramientas que lo usa!

Esto me parece que podría ser un error en el compilador F #, pero dado que nunca he mirado la especificación F #, siempre es posible que se permita/especifique el comportamiento.

+0

+1: Tuve que leerlo unas cuantas veces para captar 'del mismo nombre'. OMI la última parte de la oración debe ser ** NEGRITA ** también. – leppie

+0

Eso es _got_ ser un error. ¿Derecha? – Daniel

+0

@Daniel: No puedo pensar en una razón por la cual 'hidebysig' se debe omitir. (Nunca supe esto) – leppie

Cuestiones relacionadas