CSharp - Extension Methods Resolution and Ambiguity

Extension Methods Ambiguity and

An extension method cannot be accessed unless its class is in scope via imported namespace.

Suppose we have the following extension method called IsFirstLetterUpperCase:

using System;

namespace Utils
{
     public static class StringHelper
     {
         public static bool IsFirstLetterUpperCase (this string s)
         {
             if (string.IsNullOrEmpty(s)) 
                return false;
             return char.IsUpper (s[0]);
         }
     }
}

To use IsFirstLetterUpperCase, import Utils to avoid a compile-time error:

namespace MyApp
{
       using Utils;

       class Test
       {
         static void Main() => Console.WriteLine ("Perth".IsFirstLetterUpperCase());
       }
}

Extension methods versus instance methods

Compatible instance methods take precedence over an extension method.

In the following example, Test's Test method will always take precedence-even when called with an argument x of type int:

class Test
{
       public void Test (object x) { }    // This method always wins
}

static class Extensions
{
       public static void Test (this Test t, int x) { }
}

To call the extension method from the code above is use static syntax:

Extensions.Test(...).

Extension methods versus extension methods

If two extension methods have the same signature, the extension method must be called as an ordinary static method.

If one extension method has more specific arguments, however, the more specific method takes precedence.

To illustrate, consider the following two classes:

static class StringHelper
{
       public static bool IsFirstLetterUpperCase (this string s) {...}
}
static class ObjectHelper
{
       public static bool IsFirstLetterUpperCase (this object s) {...}
}

The following code calls StringHelper's IsFirstLetterUpperCase method:

bool test1 = "test".IsFirstLetterUpperCase();

Classes and structs are considered more specific than interfaces.