Interfaces in C#

Interface in C#
The convention in C# is to let the name of an interface start with a capital i. Most simple implementation of interface:

    public interface ILeft
    {
        void Move();
    }

    public class MoveableOject : ILeft
    {
        //without public we get an error
        public void Move()
        {
            Console.WriteLine("Left moving");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MoveableOject mo = new MoveableOject();
            mo.Move();
            Console.ReadKey();
        }
    }

Explicit interface implementation of interface in C#
We need to implement explicit interface when we need want to tell which interface we are implementing. This may be useful when we have same method in both interfaces that we are going to implement. Consider the example.

    public interface ILeft
    {
        void Move();
    }

    public class MoveableOject : ILeft
    {
          //Se there is no public  and the interface name is visible in front of the method.
        void ILeft.Move()
        {
            Console.WriteLine("Left moving");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //Derived class can't cast to base class
            //MoveableOject moError = (ILeft) new MoveableOject(); //Error??
            //ILeft  moError = new MoveableOject(); //OK moError declared as ILeft
            MoveableOject mo = new MoveableOject();
            ((ILeft)mo).Move();
            ((ILeft)new MoveableOject()).Move(); // same as previous statement
            Console.ReadKey();
        }
    }

Implementing multiple interface in C# explicit way

        public interface ILeft
        {
            void Move();
        }
        public interface IRight
        {
            void Move();
        }

        public class MoveableOject : ILeft, IRight
        {
             void ILeft.Move()
            {
                Console.WriteLine("Left moving");
            }
             void IRight.Move()
            {
                Console.WriteLine("Right moving");
            }
        }

        class Program
        {
            static void Main(string[] args)
            {
                MoveableOject mo =   new MoveableOject();
                ((ILeft)mo).Move();
                ((IRight)mo).Move();
                Console.ReadKey();
            }
        }
interface IReadOnlyInterface
{
 int Value { get; }
}
struct ReadAndWriteImplementation:IReadOnlyInterface
{
 public int Value { get; set; }
}

In this case, the implementing class adds an extra set accessor. The advantage of using this pattern is that if a user accesses our class through its interface, it will see only the get accessor. Direct users of the class will see both the get and the set accessor.

Creating an interface with a generic type parameter
We can create concrete implementations of your Repository<T> for different classes. For example, we can have an IRepository<Product> and an IRepository<Order>. Generic interfaces can have multiple type parameters and type constraints as needed.

interface IRepository<T>
{
    T FindById ( int id );
    IEnumerable<T> All ( );
}

class Product<T>:IRepository<T>
{
    List<T> mList = new List<T> ( );
    public T FindById ( int id )
    {
        return mList[id];
    }
   public  IEnumerable<T> All ( )
    {
        return mList;
    }
    public void Add(T a)
    {
        mList.Add ( a );
    }
}

public class Program
{
    public static void Main ( )
    {
        Product<int> pr = new Product<int> ( );
        pr.Add ( 4 );
        int t = pr.FindById ( 0 );
        Console.WriteLine ( t );
    }
}
interface IEntity
{
    int Id { get; }
}

//T must be IEntity type or a type derived from IEntity
class Repository<T> where T : IEntity
{
    protected IEnumerable<T> _elements;
    public Repository ( IEnumerable<T> elements )
    {
        _elements = elements;
    }
    public T FindById ( int id )
    {
        return _elements.SingleOrDefault ( e => e.Id == id );
    }
}

class Order : IEntity
{
    public int Id
    {
        get
        {
            return 0;
        }
    }
}

class OrderRepository : Repository<Order>
{
    public OrderRepository ( IEnumerable<Order> orders ) : base ( orders )
    {
    }
    public IEnumerable<Order> FilterOrdersOnAmount ( decimal amount )
    {
        List<Order> result = null;
        // Some filtering code
        return result;
    }
}

public class Program
{
    public static void Main ( )
    {
        List<Order> orderlist = new List<Order> ( );
        OrderRepository repo = new OrderRepository ( orderlist );
    }
}

Virtual methods
Marking a method virtual allows derived classes to override the method. The derived class can choose to completely replace or to extend the behavior of the base class.


class Base
{
    public virtual void Ececute()
    {
        Console.WriteLine ( "Base.Ececute" );
    }
}
class Derived : Base
{
    public   override void  Ececute ( )
    {
        Console.WriteLine ( "Derived.Ececute start" );
        base.Ececute ( );
        Console.WriteLine ( "Derived.Ececute end" );
    }
}

public class Program
{
    public static void Main ( )
    {
        Base baseclass = new Derived ( );
        baseclass.Ececute ( );
    }
}

Output of the program:

        Derived.Ececute start
        Base.Ececute
        Derived.Ececute end

If a base class doesn’t declare a method as virtual, a derived class can’t override the method. It can, however, use the new keyword, which explicitly hides the member from a base class (this is different from using the new keyword to create a new instance of an object). If we don't use the new keyword then it generates a warning.

class Base
{
    public virtual void Ececute()
    {
        Console.WriteLine ( "Base.Ececute" );
    }
}
class Derived : Base
{
    public   new void  Ececute ( )
    {
        Console.WriteLine ( "Derived.Ececute start" );
        base.Ececute ( );
        Console.WriteLine ( "Derived.Ececute end" );
    }
}

public class Program
{
    public static void Main ( )
    {
        Base baseclass = new Derived ( );
        baseclass.Ececute ( );
    }
}

Output of the program.

        Base.Ececute

Standard .NET Framework interfaces
We can implement interfaces provided by the .NET framework and can use the functionalities provided by .NET framework.

//Don't use this code if you try the example, this is just for illustration
//because other methods just as sort etc are not declared here
public interface IComparable
{
 int CompareTo(object obj);
}

This interface has been implemented for sorting DateTime objects.

class Order : IComparable
{
    public DateTime Created { get; set; }
    public int CompareTo(object obj)
    {
        if(obj == null)
        {
            return 1;
        }
        Order o = obj as Order;
        if(o == null)
        {
            throw new ArgumentException ( "Object is not an order" );
        }
        // if this one is bigger than o.Created then returns +
        // For example, 5 is this and o.Created is 1 will return +1
        //For example 5 is this and o.Created is 10 will return -1
        return this.Created.CompareTo ( o.Created );
    }
}

public class Program
{
    public static void Main ( )
    {
        List<Order> orders = new List<Order>
        {
        new Order{Created = new DateTime(2012, 12, 1)},
        new Order{Created = new DateTime(2013, 12, 2)},
        new Order{Created = new DateTime(2012, 12, 1)},
        new Order{Created = new DateTime(2012, 12, 13)},
        new Order{Created = new DateTime(2010, 12, 10)},
        new Order{Created = new DateTime(2011, 12, 11)}
        };
        orders.Sort ( );
        foreach(Order d in orders)
        {
            Console.WriteLine ( d.Created.ToShortDateString ( ) );
        }
    }
}

IEnumerable and IEnumerator interface
The GetEnumerator function on an IEnumerable returns an IEnumerator. Let's take a look in the following example.

public class Program
{
    public static void TestIEnumerable(IEnumerable<int> enumerableList)
    {
        foreach (int i in enumerableList)
        {
            Console.WriteLine ( i );
        }
    }

    public static void TestIEnumerator ( IEnumerator<int> enumeratorList )
    {
        while (enumeratorList.MoveNext ( ))
        {
            Console.WriteLine ( enumeratorList.Current );
        }  
    }

    public static void Main ( )
    {
        List<int> numbers = new List<int> { 1, 6, 7, 8, 9, 10, 12 };
        //Print all numbers
        foreach (int i in numbers)
        {
            Console.WriteLine ( i );
        }
        Console.WriteLine ( "\n" );

        IEnumerable<int> ienum = (IEnumerable<int>)numbers;
        //Print all numbers
        foreach (int i in ienum)
        {
            Console.WriteLine ( i );
        }

        //Get IEnumerator  from IEnumerable also
        IEnumerator<int> testenumarate = ienum.GetEnumerator ( );

        //Careful the following lines crash the app
        //IEnumerator ienumrat = (IEnumerator)numbers;
        IEnumerator<int> ienumrat = numbers.GetEnumerator ( );

        Console.WriteLine ( "\n" );
        while (ienumrat.MoveNext ( ))
        {
            Console.WriteLine ( ienumrat.Current );
        }

        TestIEnumerable ( ienum );

        //Without reassigning the list is at the end  but for IEnumerable it is not the case
        ienumrat = numbers.GetEnumerator ( );
        TestIEnumerator ( ienumrat );

        //Nothing is printed with the following call because IEnumerator remember the index
        // since we have called another TestIEnumerator already. If we return from that method
        // in the middle then following method would have continue from that index
        TestIEnumerator ( ienumrat );

        //All are called as usual because IEnumerable does not remember the last  index
        TestIEnumerable ( ienum );
    }
}

Implementing IEnumerable on a custom type:

//Remember to include  using System.Collections;
class Person
{
    public Person ( string firstname, string lastname )
    {
        FirstName = firstname;
        LastName = lastname;
    }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public override string ToString ( )
    {
        return FirstName + " " + LastName;
    }
}

class People : IEnumerable<Person>
{
    Person [ ] people;
    public People ( Person [ ] people )
    {
        this.people = people;
    }

    public IEnumerator<Person> GetEnumerator ( )
    {
        for (int index = 0; index < people.Length; index++)
        {
            yield return people [ index ];
        }
    }

    IEnumerator IEnumerable.GetEnumerator ( )
    {
        return GetEnumerator ( );
    }
}

public class Program
{
    public static void Main ( )
    {
        List<Person> peopleList = new List<Person> 
        {
            new Person ("Mahbub", "Rahman"),
            new Person ("Karim", "Tarim"),
            new Person ("Karim", "Tarim"),
            new Person ("Karim", "Tarim"),
            new Person ("Karim", "Tarim")
        };

        People pep = new People ( peopleList.ToArray() );

        IEnumerable<Person> ienum = (IEnumerable<Person>)pep;
        foreach (Person i in ienum)
        {
            Console.WriteLine ( "firstname = {0}, lastname = {1}", i.FirstName, i.LastName );
        }

        Console.WriteLine ( "\n\n");
        IEnumerator<Person> etr = ienum.GetEnumerator();
        while (etr.MoveNext ( ))
        {
            Console.WriteLine ( "firstname = {0}, lastname = {1}", etr.Current.FirstName, etr.Current.LastName );
        }
    }
}

Example of IDisposable interface

public class OwnTextFile : IDisposable
{
    private FileStream str;
    private bool id;
    public OwnTextFile ( string filename )
    {
        str = new FileStream ( filename, FileMode.OpenOrCreate );
        Console.WriteLine ( "Object " + GetHashCode ( ) + " created." );
        Console.WriteLine ( "Using file: " + filename );
    }

    public void insertvalue ( string buf )
    {
        if (id == true)
        {
            throw new ObjectDisposedException ( "I've been disposed!" );
        }

        StreamWriter wr = new StreamWriter ( str );
        wr.WriteLine ( System.DateTime.Now );
        wr.WriteLine ( buf );
        wr.Close ( );
    }

    public void Dispose ( )
    {
        if (id == true)
            return;
        str.Close ( );
        str = null;
        id = true;
        GC.SuppressFinalize ( this );

        Console.WriteLine ( "Object " + GetHashCode ( ) + " disposed." );
    }
}

public class Program
{
    public static void Main ( )
    {
        OwnTextFile textfile = new OwnTextFile ( "c:\\temp\\demo.txt" );
        textfile.insertvalue ( "Example of IDisposable" );
        textfile.Dispose ( );
        textfile = null;
        Console.WriteLine ( "Press Space to collect the garbage..." );
        GC.Collect ( );  
    }
}

The IDiposable interface offers one method: Dispose, which will free any unmanaged resources immediately.

StreamWriter stream = File.CreateText("temp.dat");
stream.Write("some data");
stream.Dispose();
File.Delete("temp.dat");

To make sure that our resources are always cleaned up, we need to wrap all types that implement IDisposable in a try/finally statement. Because this is so common, C# has a special statement for this: the using statement. The using statement is translated by the compiler in a try/finally statement that calls Dispose on the object. Because of this, the using statement can be used only with types that implement IDisposable.

public class MyClass : IDisposable
{
    public void Method(bool shouldThrow)
    {        
        Console.WriteLine ( "A Mehod being called" );
        if (shouldThrow)
        {
            Exception e = new Exception ( "Own exception Message" );
            throw e;
        }
    }

    public void Dispose ( )
    {
        Console.WriteLine ( "Idisposal Being called" );
    }
}

public class Program
{
    public static void Main ( )
    {       
        using (StreamWriter stream = File.CreateText ( "temp.dat" ))
        {
            stream.Write ( "some data" );
            stream.Dispose ( );
            File.Delete ( "temp.dat" ); 
        }
        //MyClass myc = new MyClass ( );
        //myc.Method ( true );
        using (MyClass myc = new MyClass ( ))
        {
            myc.Method ( false );
        }
    }
}