Gaurav123 Gaurav123 - 2 months ago 5
C# Question

OOPS Concepts: What is the difference in passing object reference to interface and creating class object in C#?

I have a class,

CustomerNew
, and an interface,
ICustomer
:

public class CustomerNew : ICustomer
{
public void A()
{
MessageBox.Show("Class method");
}

void ICustomer.A()
{
MessageBox.Show("Interface method");
}


public void B()
{
MessageBox.Show("Class Method");
}
}

public interface ICustomer
{
void A();
}


I am very confused between these two code of lines.

ICustomer objnew = new CustomerNew();
CustomerNew objCustomerNew = new CustomerNew();
objnew.B(); // Why this is wrong?
objCustomerNew.B(); // This is correct because we are using object of class


The first line of code means we are passing object reference of CustomerNew class in
objnew
, am I correct? If yes, then why can I not access method B() of the class with
interface objnew
?

Can someone explain about these two in detail.

Answer

Actually an interface is also a type (you can't create instances of interfaces since they'are just metadata).

Since CustomerNew implements ICustomer, an instance of CustomerNew can be upcasted to ICustomer. When a CustomerNew is typed as ICustomer you can only access ICustomer members.

This is because C# is a strongly-typed language, thus, in order to access a particular member (i.e. methods, properties, events...) you need an object reference to be qualified by the type which defines the members you want to access (i.e. you need to store CustomerNew object in a reference of type CustomerNew to access the method B).

Update

OP said:

So due to upcasting we can only access those methods which are inside interface, correct ? UPCASTING is the main reason behind this ?

Yes. An easy explanation is an object which implements ICustomer shouldn't mandatorily be CustomerNew. You need to downcast an ICustomer reference to CustomerNew to be able to access CustomerNew members.

As both classes and interfaces are types, and C# is a strongly-typed language, you access object members by providing its actual type. This is why you need to use casts.

For example, your code does an implicit upcast:

// This is an implicit cast that's equivalent to
// ICustomer objnew = (ICustomer)new CustomerNew()
ICustomer objnew = new CustomerNew();

Implicit upcasts are possible because the compiler already knows CustomerNew implements ICustomer introspecting CustomerNew metadata, while you can't implictly-downcast a ICustomer reference because who knows who implements ICustomer? It can be either CustomerNew or any other class or even an struct:

ICustomer asInterface = new CustomerNew();

// ERROR: This won't compile, you need to provide an EXPLICIT DOWNCAST
CustomerNew asClass1 = asInterface;

// OK. You're telling the compiler you know that asInterface
// reference is guaranteed to be a CustomerNew too!
CustomerNew asClass2 = (CustomerNew)asInterface;

If you're not sure that an ICustomer is a CustomerNew, you can use the as operator, which won't throw an exception during run-time if the cast isn't possible:

// If asInterface isn't also a CustomerNew, the expression will set null
CustomerNew asClass3 = asInterface as CustomerNew;