3

I know that we can't create instance of Interface. but why we can write Interface on left side? Are those only references of Interface (for classes that implement this one) instead instance?

If we can't create instance of Interface, what type is P in this example?

string[] names = {"John", "Bob", "Mark"};
IEnumerable<string> P = names.Where(n => n.Contains('o'));
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
Boolor
  • 45
  • 4
  • 1
    "If we can't create instance of Interface, what type is P in this example?" We don't have to know, and it is kind of the *point* of interfaces. It is a type that implements IEnumerable. The precise type doesn't matter to the user. – dureuill Feb 26 '14 at 14:11
  • You might want to read this: http://stackoverflow.com/questions/6802573/c-sharp-interfaces-whats-the-point – Paddy Feb 26 '14 at 15:07

5 Answers5

6

P is of type IEnumerable<string>

Here you are declaring the type of the local variable P.

P holds the type of IEnumerable<string>, and while you aren't instantiating the interface directly, you can instantiate a concrete class but simply hold a reference to the interface.

The instance returned here by the Where() call needs to only adhere to the contract that IEnumerable<string> defines.

Simon
  • 9,197
  • 13
  • 72
  • 115
3

You can't create an instance of an interface, but you can create an instance of something that implements it.

What you do in your example, is simply fetch something (p) that is known to adhere to the contract that IEnumerable<string> defines.

It's easier to grasp the concept if you think of it in slightly simpler terms:

IBeast mrJuggles = new Tiger();

Mr.Juggles is now a Tiger - but also an IBeast. We don't explicitly create an IBeast, we just specify that the thing we do create, will behave as an IBeast, and that we therefore will be able to treat it as an IBeast.

Kjartan
  • 18,591
  • 15
  • 71
  • 96
2

I'll try to explain this more conceptually.

but why we can write Interface on left side?

We can, because it means: "this object is something that implements this interface".

Interface by itself is not "something" - that's why you can't instantiate it directly - it's only a contract.

An interface is useless unless you define some object that is guaranteed to implement the contract expressed by it (and expose such and such methods etc.). That's the use you make of interfaces. Without this, they'd make no sense.

The contract itself is an abstract concept. It needs something to embody it - an object that fullfills it.

Have a look at the following example:

using System.Collections.Generic;

namespace App
{
    class Program
    {
        class Example
        {
            List<string> list = new List<string> { "a", "b", "c" };

            public IEnumerable<string> AsEnumerable()
            {
                return list;
            }
        }

        static void Main(string[] args)
        {
            IEnumerable<string> foo = new Example().AsEnumerable();
            List<string> bar = (List<string>)foo;
        }
    }
}

You know it doesn't crash?

IEnumerable<string> in this line:

IEnumerable<string> foo = new Example().AsEnumerable();

actually means: "foo is something that we know to implement IEnumerable".

But it is still that something. It can't be only IEnumerable and nothing but. IEnumerable is just something that we happen to know about this something.

Otherwise we couldn't cast it back to List<string>, could we? (This is actually a common caveat in C#, because the caller could do this cast, therefore gaining access to Add and Remove methods and messing with the contents of our list even though we intended them not to. It's encapsulation leakage).

In other words: IEnumerable<string> is the way we look at this object.

EDIT:

As @Kjartan suggested, you could verify this all like so:

bool isFooIEnumerable = foo is IEnumerable<string>; // it's true 
bool isBarIEnumerable = bar is IEnumerable<string>; // true again
bool isFooList = foo is List<string>; // yup. true
bool isBarList = bar is List<string>; // true all the way
Konrad Morawski
  • 8,307
  • 7
  • 53
  • 91
  • 1
    Actually, I always though of it the other way around; `foo` is an `IEnumerable`, because it has precisely the attributes required to be defined as one. That does not mean it can't be something else too. – Kjartan Feb 26 '14 at 14:19
  • 1
    @Kjartan I rephrased. – Konrad Morawski Feb 26 '14 at 14:28
  • Better. :) PS: If you add a clause like `var isFooIEnumerable = (foo is IEnumerable)` and `var isBarList = (bar is List)`, and both the other way around too, you'll get `true` in all 4 cases, and your code might make the point even clearer. :) – Kjartan Feb 26 '14 at 14:39
1

On the left hand side you declare the type of variable.

IEnumerable<string> stringEnumerator

You tell to the compiler that from this moment under value stringEnumerator can be presented a null reference or reference to object that is a string enumerator.

So when you have an expression like

IEnumerable<string> P = names.where(n => n.Contains('o'));

You say, create a variable p that will represent IEnumerable<string> and assign to it result of names.where(n => n.Contains('o'));

0

Exactly, if the left-hand side part in an assignment is typed as an interface type, it means that that left-hand side part (variable or such) is a reference to any instance of a class that implements said interface.

In the presented example, P is a reference to an instance of some internal framework class that implements IEnumerable<string>. As it is some internal class (presumeably hidden within the implementation of Enumerable), we do not even have access to the class name (and thus could not declare any variable of that type). In fact, Microsoft might be changing the actual class that is returned by Where with every .NET version. However, neither would we notice that, nor do we have to care, as all we need to know is that something that implements IEnumerable<string> will be returned, hence we also just declare the variable P as referencing something that implements IEnumerable<string> rather than as a concrete class.

O. R. Mapper
  • 20,083
  • 9
  • 69
  • 114