none
C# 7.3 Improved overload candidates RRS feed

  • Question

  • Hi

    According to Improved overload candidates

    In every release, the overload resolution rules get updated to address situations where ambiguous method invocations have an "obvious" choice. This release adds three new rules to help the compiler pick the obvious choice:

    1. When a method group contains both instance and static members, the compiler discards the instance members if the method was invoked without an instance receiver or context. The compiler discards the static members if the method was invoked with an instance receiver. When there is no receiver, the compiler includes only static members in a static context, otherwise both static and instance members. When the receiver is ambiguously an instance or type, the compiler includes both. A static context, where an implicit this instance receiver cannot be used, includes the body of members where no this is defined, such as static members, as well as places where this cannot be used, such as field initializers and constructor-initializers.
    2. When a method group contains some generic methods whose type arguments do not satisfy their constraints, these members are removed from the candidate set.
    3. For a method group conversion, candidate methods whose return type doesn't match up with the delegate's return type are removed from the set.

    Can you please explain the 3 new rules with example code snippet?  

    Here's a vain attempt especially concerning rule 1:

    using System;

    class OverloadResolution
    {
        void Method(float value) { } // all calls resolved to that overload
        void Method(double value) { }
        // void Method(decimal value) { }

        public void Print()
        {
            Method(char.MaxValue);
            Method(byte.MaxValue);
            Method(short.MaxValue);
            Method(int.MaxValue);
            Method(long.MaxValue);
            Method(float.MaxValue);
        }
    }

    class X
    {
        public void Method(string s)
        {
            Console.WriteLine("X Instance Method: {0}", s);
        }
    }

    class Y : X
    {
        public static void Method(string s)
        {
            Console.WriteLine("Y Static Method: {0}", s);
        }
    }

    class Program : Y
    {
        static void Main()
        {
            OverloadResolution overload = new OverloadResolution();
            overload.Print();

            Y.Method("The compiler discards the instance members if the method was invoked without an instance receiver or context");
            X x = new X();
            x.Method("The compiler discards the static members if the method was invoked with an instance receiver");
            Method("When there is no receiver, the compiler includes only static members in a static context");
            Program.Method("The compiler discards the instance members if the method was invoked without an instance receiver or context");
        }
    }

    Thanks






    • Edited by recherche Saturday, October 27, 2018 7:23 PM Added code
    Saturday, October 27, 2018 7:08 PM

Answers

  • Check the today’s BetterCandidates.cs file:

     

    It contains a series of strings (var source = @“…”) with sample codes for various cases. You can extract and check them.

     

    An example for New Rule 3:

    public class Program

    {

        static void Main()

        {

            M( Program.Q ); // prints "2" in C# 7.3

        }

     

        static void M( D1 d ) { System.Console.WriteLine( 1 ); }

        static void M( D2 d ) { System.Console.WriteLine( 2 ); }

     

        static void Q( A a ) { }

        static void Q( B b ) { }

    }

    delegate int D1( A a );

    delegate void D2( B b );

     

    class A { }

    class B { }

     


    • Edited by Viorel_MVP Saturday, October 27, 2018 9:19 PM
    • Marked as answer by recherche Monday, October 29, 2018 12:22 PM
    Saturday, October 27, 2018 9:14 PM
  • Hi recherche,

    Please check the link that Viorel_ mentioned, which provide related code sample for rule 1, such as:

    //When a method group contains both instance and static members, we discard the static members if invoked with an instance receiver.
    
    using System;
    class Program
    {
        static void Main()
        {
            var q = from x in new Q() select x;
        }
    }
    class Q
    {
        public static object Select(Func<A, A> y)
        {
            Console.WriteLine(1);
            return null;
        }
        public object Select(Func<B, B> y)
        {
            Console.WriteLine(2);
            return null;
        }
    }
    class A {}
    class B {}

    Best regards,

    Zhanglong 


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by recherche Monday, October 29, 2018 12:22 PM
    Monday, October 29, 2018 2:25 AM
    Moderator

All replies

  • Check the today’s BetterCandidates.cs file:

     

    It contains a series of strings (var source = @“…”) with sample codes for various cases. You can extract and check them.

     

    An example for New Rule 3:

    public class Program

    {

        static void Main()

        {

            M( Program.Q ); // prints "2" in C# 7.3

        }

     

        static void M( D1 d ) { System.Console.WriteLine( 1 ); }

        static void M( D2 d ) { System.Console.WriteLine( 2 ); }

     

        static void Q( A a ) { }

        static void Q( B b ) { }

    }

    delegate int D1( A a );

    delegate void D2( B b );

     

    class A { }

    class B { }

     


    • Edited by Viorel_MVP Saturday, October 27, 2018 9:19 PM
    • Marked as answer by recherche Monday, October 29, 2018 12:22 PM
    Saturday, October 27, 2018 9:14 PM
  • Thank you for the reply and partial answer.

    Got rule 2 from your answer for rule 3:

    using System;
    
    delegate int D1(A a);
    delegate void D2(B b); // delegate void return
    
    class A { }
    class B { }
    
    class Foo { }
    class Bar { }
    
    static class FooExtensions
    {
        public static TFoo Frob<TFoo>(this TFoo foo) where TFoo : Foo { Console.WriteLine("FooExtensions Frob");  return null; }
        public static TFoo Brob<TFoo>(this TFoo foo) where TFoo : Foo { Console.WriteLine("FooExtensions Brob");  return null; }
    }
    
    static class BarExtensions
    {
        public static TBar Frob<TBar>(this TBar bar) where TBar : Bar { Console.WriteLine("BarExtensions Frob");  return null; }
    }
    
    class MethodGroupConversion
    {
        private void M(D1 d) { Console.WriteLine("delegate int return"); }
        private void M(D2 d) { Console.WriteLine("delegate void return"); } // delegate void return
    
        private void Q(A a) { }
        private void Q(B b) { }
    
        public void Print()
        {
            // Pre-C# 7.3 // Error CS0121  The call is ambiguous between the following methods or properties: 'MethodGroupConversion.M(D1)' and 'MethodGroupConversion.M(D2)'  
            M(Q); // delegate void return // Prints "delegate void return" in C# 7.3
            // Pre-C# 7.3 // Error CS0121  The call is ambiguous between the following methods or properties: 'FooExtensions.Frob<TFoo>(TFoo)' and 'BarExtensions.Frob<TBar>(TBar)'    
            new Foo().Frob();
        }
    }
    
    class Program
    {
        static void Main()
        {
            MethodGroupConversion groupConversion = new MethodGroupConversion();
            groupConversion.Print();
        }
    }

    Can you please elaborate the aforementioned new rule 1 with example code snippet?


    What is the scenario for replicating the ambiguity mentioned in the rule 1?

    Thanks


    • Edited by recherche Sunday, October 28, 2018 11:03 AM typo
    Sunday, October 28, 2018 11:02 AM
  • Hi recherche,

    Please check the link that Viorel_ mentioned, which provide related code sample for rule 1, such as:

    //When a method group contains both instance and static members, we discard the static members if invoked with an instance receiver.
    
    using System;
    class Program
    {
        static void Main()
        {
            var q = from x in new Q() select x;
        }
    }
    class Q
    {
        public static object Select(Func<A, A> y)
        {
            Console.WriteLine(1);
            return null;
        }
        public object Select(Func<B, B> y)
        {
            Console.WriteLine(2);
            return null;
        }
    }
    class A {}
    class B {}

    Best regards,

    Zhanglong 


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by recherche Monday, October 29, 2018 12:22 PM
    Monday, October 29, 2018 2:25 AM
    Moderator
  • Thank you for the answer.
    Monday, October 29, 2018 12:22 PM