Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9218363
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 18, 20262026-06-18T02:50:45+00:00 2026-06-18T02:50:45+00:00

Say, I have member this.Test (x: ‘a) = printfn generic 1 member this.Test (x:

  • 0

Say, I have

member this.Test (x: 'a) = printfn "generic"
                           1
member this.Test (x: Object) = printfn "non generic"
                               2

If I call it in C#

var a = test.Test(3);         // calls generic version
var b = test.Test((object)3); // calls non generic version
var c = test.Test<object>(3); // calls generic version

However, in F#

let d = test.Test(3);  // calls non generic version
let e = test.Test<int>(3); // calls generic version

So I have to add type annotation so as to get the correct overloaded method. Is this true? If so, then why F# doesn’t automatically resolve correctly given that the argument type is already inferred? (what is the order of F#’s overload resolution anyway? always favor Object than its inherited classes?)

It is a bit dangerous if a method has both overloads, one of them takes argument as Object type and the other one is generic and both return the same type. (like in this example, or Assert.AreEqual in unit testing), as then it is very much likely we get the wrong overloading without even notice (won’t be any compiler error). Wouldn’t it be a problem?

Update:

Could someone explain

  • Why F# resolves Assert.AreEqual(3, 5) as Assert.AreEqual(Object a, Object b) but not Assert.AreEqual<T>(T a, T b)

  • But F# resolves Array.BinarySearch([|2;3|], 2) as BinarySearch<T>(T[]array, T value) but not BinarySearch(Array array, Object value)

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-18T02:50:46+00:00Added an answer on June 18, 2026 at 2:50 am

    F# Method overload resolution not as smart as C#?

    I don’t think it’s true. Method overloading makes type inference much more difficult. F# has reasonable trade-offs to make method overloading usable and type inference as powerful as it should be.

    When you pass a value to a function/method, F# compiler automatically upcasts it to an appropriate type. This is handy in many situations but also confusing sometimes.

    In your example, 3 is upcasted to obj type. Both methods are applicable but the simpler (non-generic) method is chosen.

    Section 14.4 Method Application Resolution in the spec specifies overloading rules quite clearly:

    1) Prefer candidates whose use does not constrain the use of a
    user-introduced generic type annotation to be equal to another type.

    2) Prefer candidates that do not use ParamArray conversion. If two
    candidates both use ParamArray conversion with types pty1 and pty2,
    and pty1 feasibly subsumes pty2, prefer the second; that is, use the
    candidate that has the more precise type.

    3) Prefer candidates that do not have
    ImplicitlyReturnedFormalArgs.

    4) Prefer candidates that do not have
    ImplicitlySuppliedFormalArgs.

    5) If two candidates have unnamed actual argument types ty11…ty1n and ty21…ty2n, and each ty1i either

    a. feasibly subsumes ty2i, or

    b. ty2i is a System.Func type and ty1i is some other delegate
    type, then prefer the second candidate. That is, prefer any candidate that has the more specific actual argument types, and
    consider any System.Func type to be more specific than any other
    delegate type.

    6) Prefer candidates that are not extension members over
    candidates that are.

    7) To choose between two extension members, prefer the one that
    results from the most recent use of open.

    8) Prefer candidates that are not generic over candidates that are
    generic—that is, prefer candidates that have empty ActualArgTypes.

    I think it’s users’ responsibility to create unambiguous overloaded methods. You can always look at inferred types to see whether you’re doing them correctly. For example, a modified version of yours without ambiguity:

    type T() =
        member this.Test (x: 'a) = printfn "generic"; 1
        member this.Test (x: System.ValueType) = printfn "non-generic"; 2
    
    let t = T()
    let d = t.Test(3)  // calls non-generic version
    let e = t.Test(test) // call generic version
    

    UPDATE:

    It comes down a core concept, covariance. F# doesn’t support covariance on arrays, lists, functions, etc. It’s generally a good thing to ensure type safety (see this example).

    So it’s easy to explain why Array.BinarySearch([|2;3|], 2) is resolved to BinarySearch<T>(T[] array, T value). Here is another example on function arguments where

    T.Test((fun () -> 2), 2)
    

    is resolved to

    T.Test(f: unit -> 'a, v: 'a)
    

    but not to

    T.Test(f: unit -> obj, v: obj)
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Say I have a list of member, each of which is a custom object:
Say I have Object A which has a member of type Object B.. and
Say I have a List(Of Tag) with Tag being an object. One member of
I have a class say Test.java and it includes a member variable called errorCode
Say I have a member function that creates a new object and places it
Let's say I have a class with a member that looks like this: readonly
Lets say i have this member: @property (retain, nonatomic) Student *student; @synthesize student; Now
Let's say I have this object: public class Role { public string Name {
Say I have a type with a member function: class Thing { std::string m_name;
Say I have a class definition: class CustomClass { int member; }; Why is

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.