2014-01-12 6 views
5

я выставить следующий класс в узле А:Ошибка компиляции при переопределении универсального типа метода

public abstract class ServiceDependencyHost 
{ 
    protected virtual T ReferenceService<T>() where T : ServiceBase 
    { 
     // Virtual implementation here... 
    } 
} 

я выставить этот производный класс в отдельной сборке (B):

public sealed class ProcessServiceOperation : ServiceDependencyHost 
{ 
    public override T ReferenceService<T>() 
    { 
     // Override implementation here... 

     return base.ReferenceService<T>(); 
    } 
} 

Использование кода как показано выше, компилятор жалуется на этой линии:

return base.ReferenceService<T>(); 

Тип «T» может не следует использовать как параметр типа 'T' в родовом типе или методе A.ReferenceService(). Нет конверсии бокса или преобразования параметров типа из «T» в «System.ServiceProcess.ServiceBase».

Естественно, я попытался тиражирование ограничения в сборке B:

public override T ReferenceService<T>() where T : ServiceBase 

Но компилятор в настоящее время предупреждает на строке выше ...

Ограничения для переопределения и явных методов реализации интерфейса наследуются из базового метода, поэтому они не могут быть указаны напрямую.

This answer указывает, что мое решение должно было работать. Я хочу избежать использования рефлекса, чтобы публично публиковать этот метод. Это должно быть так просто!

Заранее благодарим любого, кто может определить, какую ошибку я делаю.

ответ

4

Проблема не связана исключительно с дженериками. Причиной проблемы является то, что метод базового класса равен protected, тогда как метод производного класса - public.

Объявление переопределения не может изменить доступность виртуального метода. Как метод переопределения, так и виртуальный метод должны иметь один и тот же модификатор уровня доступа.

Следовательно, компилятор предполагает, что эти два метода различны, и полученный метод не может наследовать where T : ServiceBase родовое ограничение от базового метода. Поскольку производный метод ничего не знает о T, он, как ожидается, жалуется, что T не может быть преобразован в ServiceBase при попытке передать его базовому методу.

+0

Смотрите мой комментарий по почте elgonzo. Спасибо, Дуглас. Интересно, почему компилятор меня заблудился: -P – AdamStone

+0

Ах, ваше объяснение о том, почему компилятор произносит эти сообщения об ошибках. Это сводится к порядку, в котором компилятор делает проверки на здравомыслие и на котором он терпит неудачу первым ... – elgonzo

4

Ошибка сообщения, кажется, вводит в заблуждение.

Обратите внимание, что вы перегрузили в защищенного виртуального метода с общественного переопределения. Это не сработает. Сделайте переопределение защищенным тоже, и код должен скомпилировать просто отлично ...

(Я не уверен, что, по-видимому, неправильное сообщение об ошибке является ошибкой или существует разумное объяснение этого конкретного поведения компилятора.)

+0

Aha!Я знал, что я идиот, мне просто нужно, чтобы кто-то указал на мое лицо горизонтально. Итак, мне нужно создать новый публичный метод и вызвать A.ReferenceService, если я хочу публиковать его публично. Спасибо, elgonzo. – AdamStone

+0

@AdamStone, учитывая, что Дуглас представил объяснение об ошибке, я думаю, что его ответ должен быть помечен вместо моего. :) – elgonzo

+0

Как спортивный из вас! Ваш приз отменен: -D – AdamStone

1

его из-за общественности => защищено. Этот компилирует штраф

public abstract class ServiceDependencyHost 
     { 
      protected virtual T ReferenceService<T>() where T : new() 
      { 
       return new T(); 
      } 
     } 

     public sealed class ProcessServiceOperation : ServiceDependencyHost 
     { 
      protected override T ReferenceService<T>() 
      { 
       // Override implementation here... 

       return base.ReferenceService<T>(); 
      } 
     } 
+0

Ненавижу, когда решение оказывается чем-то не связанным с тем, что вы считали проблемой. И это почти всегда происходит. Следовательно, я ненавижу проблемы. – AdamStone

Смежные вопросы