Реализация универсального интерфейса - PullRequest
3 голосов
/ 11 октября 2010

У меня есть универсальный интерфейс:

public interface IUnauthorizedRequestRespondable<out T> where T:class 
{
    T GetResponseForUnauthorizedRequest();
}  

(я не уверен, почему Resharper рекомендовал T "out", но это не вопрос).
В моем сценарии возвращенный объектGetResponseForUnauthorizedRequest всегда относится к типу, который реализует интерфейс.

Таким образом, все реализации интерфейса выглядят следующим образом:

public class SignInReturnedObject : IUnauthorizedRequestRespondable<SignInReturnedObject>  

(имя класса и тип в скобках всегда одинаковы).
Что кажется немного неловким - разве нет более точного способа сообщить компилятору, что метод интерфейса возвращает тип, частью которого он является?

Спасибо.

Ответы [ 5 ]

4 голосов
/ 11 октября 2010

Насколько я знаю, в настоящее время нет способа сделать это в C #.

Теоретическое примечание : функция, которая позволит вам сделать это, называется self types , но она не доступна в C #. Идея этой функции в том, что у вас есть специальный тип, который ссылается на фактический тип this, поэтому, если у вас есть специальный тип с именем self, вы, вероятно, могли бы написать что-то вроде:

public interface IUnauthorizedRequestRespondable { 
    self GetResponseForUnauthorizedRequest(); 
}   

... и фактический тип, используемый вместо self, когда у вас есть класс SignInReturnedObject, реализующий интерфейс, будет SignInReturnedObject, но, к сожалению, это не
доступно в C #: -)

2 голосов
/ 11 октября 2010

Если вы хотите использовать этот шаблон только таким способом, я бы использовал:

public interface IUnauthorizedRequestRespondable<T> where T:IUnauthorizedRequestRespondable<T>
{
    T GetResponseForUnauthorizedRequest();
}

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

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

0 голосов
/ 11 октября 2010

Поскольку T может быть любым классом (не обязательно тем классом, который вы реализуете), вам нужно назвать свой класс.

public class SignInReturnedObject : IUnauthorizedRequestRespondable<ANYCLASS>
0 голосов
/ 11 октября 2010

Вы можете создать неуниверсальную версию и просто использовать ее, но я думаю, что это больше проблем, чем оно стоит

public interface ICastUnauthorizedRequestRespondable : IUnauthorizedRequestRespondable<SignInReturnedObject>
{
}  
0 голосов
/ 11 октября 2010

На самом деле, это примерно так. Вот как работает синтаксис.

Вы можете видеть, что он используется в самом .NET с интерфейсом IEquatable - вы почти всегда сравниваете объект с самим собой, но вы всегда должны указывать свое имя класса в качестве параметра шаблона.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...