Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

C# Interface confusion

Options
  • 10-11-2011 10:46am
    #1
    Registered Users Posts: 146 ✭✭


    I understand the concept of interfaces in that they are a contract specifying boilerplate code that must be implemented when we inherit from an interface. But more and more I am seeing syntax like....

    (assuming a customer class)
    IEnumerable<customer> custs = new IEnumerable<customer>();

    Now can anyone please explain this to me? IEnumerable is merely an interface so how can we create an object like this? Why not use List<customer> custs = new . . . ?


Comments

  • Registered Users Posts: 9,579 ✭✭✭Webmonkey


    m1nder wrote: »
    I understand the concept of interfaces in that they are a contract specifying boilerplate code that must be implemented when we inherit from an interface. But more and more I am seeing syntax like....

    (assuming a customer class)
    IEnumerable<customer> custs = new IEnumerable<customer>();

    Now can anyone please explain this to me? IEnumerable is merely an interface so how can we create an object like this? Why not use List<customer> custs = new . . . ?
    I think it has something to do with COM Interop.

    Have a read of these
    http://marcgravell.blogspot.com/2009/08/who-says-you-cant-instantiate-interface.html
    http://stackoverflow.com/questions/1303717/newing-up-interfaces

    By the way, by saying List<customer> custs = ... you are removing the abstraction of how to enumerate the items. So you should probably have so that more methods can accept this and enumerate it.
    IEnumerable<customer> custs = new List<customer>();
    


  • Registered Users Posts: 385 ✭✭EoghanConway


    m1nder wrote: »
    IEnumerable<customer> custs = new IEnumerable<customer>();

    The reason is that you don't have to specify the concrete implemenation of the collection at this time - it just has to implement IEnumerable. Why would you want to do this? You may have a need (or it may simply be easier or more logical) to use a specific generic or specialised collection and not be restricted to List as per your example.


  • Registered Users Posts: 2,023 ✭✭✭Colonel Panic


    IEnumerable<int> test = new IEnumerable<int>();
    

    Cannot create an instance of the abstract class or interface 'System.Collections.Generic.IEnumerable<int>'

    You can't instantiate an interface or abstract class. It basically defines a contract through which a user can interact with a collection that makes it independent of implementation.
    IEnumerable<int> test = new List<int>();
    

    This works.


  • Registered Users Posts: 9,579 ✭✭✭Webmonkey


    IEnumerable<int> custs = new IEnumerable<int>();
    

    Cannot create an instance of the abstract class or interface 'System.Collections.Generic.IEnumerable<int>'

    You can't instantiate an interface or abstract class. It basically defines a contract through which a user can interact with a collection that makes it independent of implementation.
    IEnumerable<int> test = new List<int>();
    

    This works.
    Actually C# makes exceptions to this if you read the above links. It's horrible and should never be done.


  • Registered Users Posts: 146 ✭✭m1nder


    The reason is that you don't have to specify the concrete implemenation of the collection at this time - it just has to implement IEnumerable.

    So are you saying that you can enforce a requirement to use an interface at declaration?

    in the example . . .var IEnumerable<customer> custs = new . . .
    are you saying, declare a collection of customers in some unknown collection type that must implement IEnumerable ?


  • Advertisement
  • Registered Users Posts: 2,023 ✭✭✭Colonel Panic


    Webmonkey wrote: »
    Actually C# makes exceptions to this if you read the above links. It's horrible and should never be done.

    It doesn't really though, I mean, COM Interop is a whole different thing. In the context of what the user is talking about, generic collections, and indeed everything I can think of in the .Net framework, it's not valid and won't compile.


  • Registered Users Posts: 146 ✭✭m1nder


    IEnumerable<int> test = new List<int>();
    
    This works.


    so why not just say

    List<int> test = new List<int>();


  • Registered Users Posts: 9,579 ✭✭✭Webmonkey


    m1nder wrote: »
    so why not just say

    List<int> test = new List<int>();
    Then you are missing the point of abstraction.

    When you define test as a List<int> then you can only pass this list to methods that accept Lists or anything that inherit from lists. (Wrong see edit!)

    Edit: I wrote that the wrong way around in a panic. If you have a method that accepts List<int>, then this method can only operate on lists of ints. If you want to abstract on enumerable types, you should define the method to accept IEnumerable<int>.


  • Registered Users Posts: 9,579 ✭✭✭Webmonkey


    It doesn't really though, I mean, COM Interop is a whole different thing. In the context of what the user is talking about, generic collections, and indeed everything I can think of in the .Net framework, it's not valid and won't compile.
    Yeah you are correct. Only in the case of COM it can be done. It won't compile otherwise.


  • Registered Users Posts: 146 ✭✭m1nder


    Many thanks for all replies, I am very grateful.

    I still dont really get it though. Can anyone perhaps come up with a simple example of this abstraction and where I might use it? That might get through.


  • Advertisement
  • Registered Users Posts: 146 ✭✭m1nder


    Webmonkey wrote: »
    Then you are missing the point of abstraction.

    When you define test as a List<int> then you can only pass this list to methods that accept Lists or anything that inherit from lists.

    I cant say string s = new int()
    so why then can I say IEnumerable<int> ints = new List<int>()?
    and secondly, aren't we creating a new List<int>()here, so where is the abstraction anyway?


  • Registered Users Posts: 9,579 ✭✭✭Webmonkey


    No you can't but that's because int and string are totally different types of primatives/objects.

    Take 1 interface and 2 classes:
    ILoggable
    BankAccount
    Customer

    BankAccount and Customer both implement the ILoggable interface.
    This means you can create an object declared at a higher abstraction as follows:

    ILoggable bankAccount= new BankAccount();
    This is legal since BankAccount implements ILoggable. The same is true if BankAccount inherited ILoggable. This means we can pass bankAccount to other methods that accept "ILoggable" and then we can call methods of the ILoggable interface and we are guaranteed that BankAccount has these since it implemented the interface.

    Take the following example I coded up for you:
    namespace TestApp
    {
        public interface ILoggable
        {
           void Write();
        }
    
        class Customer : ILoggable
        {
            public void Write()
            {
                // specific code to log a customer.
                Console.Out.WriteLine("Logging customer");
            }
        }
    
        class BankAccount : ILoggable
        {
            public void Write()
            {
                // specific code to log a bank account.
                Console.Out.WriteLine("Logging bank account");
            }
        }
    
        class Logger
        {
    
            public void LogItems(IEnumerable<ILoggable> objList)
            {
                foreach (ILoggable obj in objList)
                {
                    obj.Write();
                }
            }
        }
     
        class Program
        {
            static void Main(string[] args)
            {
                BankAccount bankAccount = new BankAccount();
                Customer customer = new Customer();
    
                Logger logger = new Logger();
    
                IList<ILoggable> loggableItems = new List<ILoggable>();
                loggableItems.Add(bankAccount);
                loggableItems.Add(customer);
                logger.LogItems(loggableItems);
            }
        }
    }
    

    You can see the Logger can accept any type of object that implements the ILoggable interface. This is abstraction. We don't need to know of the concrete details of Customer or BankAccount. All we want to do is call the write method on these objects. They will do their own concrete implementations. We know that any object we pass into the Logger will implement Write as it has to because it has to implement the ILoggable interface.

    Hope that makes sense.

    By the way also look at the IEnumerable in Logger::LogItems method. Since IList inherits from the IEnumerable interface, it can be passed to the logger. We could also pass other types of collections that implement the IEnumerable interface to this logger as well and it would also work since it's possible to Enumerate the list or what ever it is. So the foreach will work on these.


  • Registered Users Posts: 2,023 ✭✭✭Colonel Panic


    Because an int isn't a string but a List implements the IEnumerable interface.

    The abstraction isn't apparent because it's a small bit of sample code.

    If you were to write a class to fetch data from a webservice, you could make methods in that class return IEnumerables instead of instances of List, so your class could use any collection that implements IEnumerable. This means if you wanted to change the code later, stuff using that code doesn't care. A lot of people talk about classes and code reuse, but really it's more about code maintenance.


  • Registered Users Posts: 11,979 ✭✭✭✭Giblet


    I want to write my own super list data structure, but I want it to be compatible with a generic interface which says "My data structure is enumerable". I then implement the required methods to do whatever the hell I want, and pass them around to whatever methods that accept an IEnumerable.

    Then some ****er comes along and wants to use lists.

    He doesn't break anything.


  • Registered Users Posts: 146 ✭✭m1nder


    @Webmonkey and everyone. Starting to get it now. Many thanks.


  • Registered Users Posts: 2,149 ✭✭✭dazberry


    Think of it as in the GoF concept of Programing to an interface, not an implementation.

    http://www.artima.com/lejava/articles/designprinciples.html

    D.


  • Moderators, Society & Culture Moderators Posts: 9,689 Mod ✭✭✭✭stevenmu


    Webmonkey wrote: »
    Then you are missing the point of abstraction.

    When you define test as a List<int> then you can only pass this list to methods that accept Lists or anything that inherit from lists.
    Actually it's the other way around, you can pass it to methods that accept a List, or anything List inherits from, I don't think you could pass it to a method which only accepts a type which inherits from list.

    This code is perfectly fine:
        public class Class1
        {
            public void foo1()
            {
                List<int> test = new List<int>();
                foo2(test);
            }
    
            public void foo2(IEnumerable<int> test)
            {
    
            }
        }
    


  • Registered Users Posts: 9,579 ✭✭✭Webmonkey


    stevenmu wrote: »
    Actually it's the other way around, you can pass it to methods that accept a List, or anything List inherits from, I don't think you could pass it to a method which only accepts a type which inherits from list.

    This code is perfectly fine:
        public class Class1
        {
            public void foo1()
            {
                List<int> test = new List<int>();
                foo2(test);
            }
    
            public void foo2(IEnumerable<int> test)
            {
    
            }
        }
    
    Ooops sorry! I should have re read what I wrote. Obviously I meant the other :)

    Just to clarify, if you define a method that takes in Lists, then you cannot pass any other IEnumerable type to it.

    Thanks for that.


Advertisement