extension-methodsbeef

How can I use an extension to add interface conformance to a type that is outside my control?


On the extensions page of the Beef documentation, it says this:

Extensions can be useful for adding interface conformance to types that are outside your control (ie: system types or types defined in another library).

Unfortunately, it doesn't provide an example of that use case, and I don't know how to proceed.

Suppose I have an interface IFooBarable:

interface IFooBarable
{
    void FooBar();
} 

And I would like to add this extension method to the system library type System.DateTime:

namespace System
{
    extension DateTime
    {
        public void FooBar()
        {
            String s = scope .();
            ToLongTimeString(s);

            Console.WriteLine("This dateTime ({}) has FooBarred", s); 
        }
    }
}

... such that DateTime can implement IFooBarable.

Is there supposed to be a way one can tell the compiler to treat DateTime as an implementation of IFooBarable? For instance, such that this compiles:

using System;

interface IFooBarable
{
    void FooBar();
}

/* extension code here */

namespace Program
{
    public class Program
    {
        static void Main()
        {
            IFooBarable t = DateTime.Now;

            t.FooBar();
        }
    }
}

Solution

  • Turns out it's as easy as using the same syntax as what indicates implementation in a class declaration. That is to say, all you need to do above is use extension DateTime : IFooBarable:

    using System;
    
    interface IFooBarable
    {
        void FooBar();
    }
    
    namespace System
    {
        extension DateTime : IFooBarable
        {
            public void FooBar()
            {
                String s = scope .();
                ToLongTimeString(s);
    
                Console.WriteLine("This dateTime ({}) has FooBarred", s); 
            }
        }
    }
    
    namespace Program
    {
        public class Program
        {
            static void Main()
            {
                IFooBarable t = DateTime.Now;
    
                t.FooBar();
            }
        }
    }
    

    You can even do this to register a method that a class already has as an implementation of an interface's method of the same name by not having anything inside the extension:

    using System;
    
    interface IFooBarable
    {
        void ToLongTimeString();
    }
    
    namespace System
    {
        extension DateTime : IFooBarable
        {
        }
    }
    
    namespace Program
    {
        public class Program
        {
            static void Main()
            {
                IFooBarable t = DateTime.Now;
    
                String s = scope .(); 
                t.ToLongTimeString(s);
    
                Console.WriteLine("{}", s);
            }
        }
    }