Почему я должен явно реализовывать член интерфейса объекта типа, если этот член уже был реализован с другим типом?
Рассмотрим следующий пример:
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
}
}
Конец редактирования