Phil Cooper
Phil Cooper

Reputation: 3133

Why do I have to explicitly implement an interface member of type object when the member has already been implemented with another type?

Consider the following example:

namespace Test
{
    interface IContract : IContract<object> { }

    interface IContract<T>
    {
        void Definition(T data);
    }

    public class SomeClass : IContract, IContract<SomeContractClass>
    {
        public void Definition(SomeContractClass data)
        {
            // ...
        }
    }

    public class SomeContractClass { }
}

I thought I would have satisfied the interface by supplying Definition(SomeContractClass data) since as stated in MDSN:

In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from Object.

But instead the compiler asks me to define it explicitly:

Error 1 'Test.SomeClass' does not implement interface member 'Test.IContract.Definition(object)'

Upvotes: 4

Views: 174

Answers (2)

Eduard Dumitru
Eduard Dumitru

Reputation: 3252

I will make a litle analogy of your situation.

You have a small company that repairs small cars.

You sign a contract with the government who needs a repair service for any type of vehicle in their diplomatic fleet (airplanes, boats, big trucks, and small cars).

You lied / made a small error the moment you made the generalization that

1) since you successfully implement

void Repair(SmallCar vehicle) 

2) and because

class SmallCar : Vehicle { }
class Airplane : Vehicle { }
class Boat : Vehicle { }
class BigTruck : Vehicle { }

somehow, the combining of points (1 + 2) => point 3 which states:

3) The government can safely refer to your small company as "The guys who repair anything" and someday consider it a good idea to ask your company to help them like so:

Airplane protocolPlane = new Airplane();
yourCompany.Repair(protocolPlane);

which is of course not true: (1 + 2) do not imply (3)

It's a good thing that this ended up as a compiler error and not runtime exception. This way you learn sooner about a small problem in the architecture.

EDIT

In your code, if you decide you really need to implement both interfaces in the SomeClass class and you don't know how to do that, you could use explicit interface implementation like so:

public class SomeClass : IContract, IContract<SomeContractClass>
{
    // Method of IContract<SomeContractClass>
    public void Definition(SomeContractClass data)
    {
        Console.WriteLine("Processing a SomeContractClass instance");            
        // ...etc
    }
    // Method of IContract hence of IContract<object>
    void IContract<object>.Definition(object data)
    {
        if (data is SomeContractClass)
          this.Definition(data as SomeContractClass);
        else
        {
          string descriptor = (null == data) 
            ? "A null reference" 
            : "An instance of " + data.GetType().Name";
          Console.WriteLine("Processing something other than a SomeContractClass instance: " + descriptor);
          // ...etc
        }
    }

}

This way, you will successfully get the following results:

class Program {
     public static void Main(string[] args) {
         SomeClass someInstance = new SomeClass();
         IContract<SomeContractClass> first= someInstance;
         IContract second = someInstance;

         someInstance.Definition(new SomeContractClass()); 
         // prints out "Processing a SomeContractClass instance"

         first.Definition(new SomeContractClass());
         // prints out "Processing a SomeContractClass instance"

         second.Definition(new SomeContractClass());
         // prints out "Processing a SomeContractClass instance"

         second.Definition( "something else" );
         // prints "Processing something other 
         // than a SomeContractClass instance: An instance of String"

         second.Definition( 123 );
         // prints "Processing something other
         // than a SomeContractClass instance: An instance of Int32"

         first.Definition( true );
         // doesn't compile saying that bool can't be converted to SomeContractClass

     }
}

END OF EDIT

Upvotes: 3

RB.
RB.

Reputation: 37222

You are implementing the interface IContract.

If we flatten the inheritance heirarchy, we can see that IContract essentially looks like this:

interface IContract
{
    void Definition(object data);
}

You do not supply a method matching the signature void Definition (object data) - the method you supply takes a SomeContractClass instead. Therefore, you get the stated error message.

However, I think the underlying issue is that your class implements both IContract and IContract<T> (which is the same as saying IContract<object> and IContract<T>). I think your design needs some work...

Upvotes: 8

Related Questions