The following F# code declares base and descendant classes. The base class has a virtual method 'Test' with a default implementaion. The descendant class overrides the base class method and also adds a new overloaded 'Test' method. This code compiles fine and presents no issues when accessing either of the descendant 'Test' methods.
F# Code:
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
However, attempting to invoke the descendant's override of 'Test' from C# results in a compilation error:
var result = td.Test(3); <- No overload for method 'Test' takes 1 arguments
The full C# Code:
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();
}
}
}
The strange thing is that VisualStudio's intellisense sees the two overloaded functions, and provides correct signatures for both. It gives no warnings or errors before the build fails, and only highlights the line afterwards.
I have re-implemented this scenario fully in C# and did not run into the same problem.
Anyone have any ideas what's going on here?
No doubt you're aware that if you omit the Test(x,y)
member from the Descendant
type -- or simply rename it Test2(x,y)
-- then the C# code will compile and run as expected.
Looking at the IL generated for your original Descendant
type offers a clue:
.method public hidebysig virtual
instance int32 Test (
int32 x
) cil managed ...
.method public
instance int32 Test (
int32 x,
int32 y
) cil managed ...
Notice that there's no hidebysig
attribute on the Test(x,y)
method.
The ECMA CLI specification has the following to say about hidebysig
. (Section 15.4.2.2, emphasis in bold is mine.)
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.
So, the F# compiler omits the hidebysig
attribute, meaning that the Test(x,y)
method hides all other methods named Test
. Although hidebysig
is only "for the use of tools", it appears that the C# compiler is one of those tools that uses it!
This looks to me like it could be a bug in the F# compiler, but since I've never looked at the F# spec it's always possible that this is allowed/specified behaviour.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With