Почему я должен явно реализовывать член интерфейса объекта типа, если этот член уже был реализован с другим типом?

Рассмотрим следующий пример:

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 { }
}

Я думал, что я бы удовлетворил интерфейс, поставив Definition(SomeContractClass data) поскольку, как указано в MDSN:

В унифицированной системе типов C# все типы, предопределенные и определяемые пользователем, ссылочные типы и типы значений, наследуются прямо или косвенно от Object.

Но вместо этого компилятор просит меня определить это явно:

Ошибка 1 "Test.SomeClass" не реализует элемент интерфейса "Test.IContract.Definition(объект)"

2 ответа

Решение

Вы реализуете интерфейс IContract,

Если мы сгладим наследственную наследственность, мы увидим, что IContract по сути выглядит так:

interface IContract
{
    void Definition(object data);
}

Вы не предоставляете метод, соответствующий подписи void Definition (object data) - метод, который вы поставляете, требует SomeContractClass вместо. Таким образом, вы получите указанное сообщение об ошибке.

Тем не менее, я думаю, что основная проблема заключается в том, что ваш класс реализует оба IContract а также IContract<T> (что то же самое, что сказать IContract<object> а также IContract<T>). Я думаю, что ваш дизайн нуждается в некоторой работе...

Я сделаю небольшую аналогию вашей ситуации.

У вас есть небольшая компания, которая занимается ремонтом небольших автомобилей.

Вы подписываете договор с правительством, которое нуждается в ремонте любого типа транспортного средства в своем дипломатическом флоте (самолеты, лодки, большие грузовики и маленькие автомобили).

Вы солгали / сделали небольшую ошибку в тот момент, когда вы сделали

1) так как вы успешно внедрили

void Repair(SmallCar vehicle) 

2) и потому

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

каким-то образом объединение точек (1 + 2) => точка 3, которая гласит:

3) Правительство может смело называть вашу маленькую компанию "парнями, которые что-то ремонтируют", и однажды посчитает хорошей идеей попросить вашу компанию помочь им вот так:

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

что, конечно, не соответствует действительности: (1 + 2) не означает (3)

Хорошо, что это закончилось ошибкой компилятора, а не исключением времени выполнения. Таким образом, вы быстрее узнаете о небольшой проблеме в архитектуре.

РЕДАКТИРОВАТЬ

В вашем коде, если вы решите, что вам действительно нужно реализовать оба интерфейса в классе SomeClass, и вы не знаете, как это сделать, вы можете использовать явную реализацию интерфейса следующим образом:

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
        }
    }

}

Таким образом, вы успешно получите следующие результаты:

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

     }
}

Конец редактирования

Другие вопросы по тегам