Как написать неявное преобразование из интерфейса в другой тип? - PullRequest
3 голосов
/ 21 апреля 2011

Я пытаюсь сделать что-то вроде ниже:

public class SomeWrapper : ISomeWrapper{

  public static implicit operator ActualRec(ISomeWrapper someWrapper)
        {
            return ((SomeWrapper)someWrapper).SomeInfo;
        }
}

Но этот код не работает, говоря: «Либо параметр, либо возвращаемый тип должны иметь тип SomeWrapper».

Я понимаю проблему, которую ставит компиляция. Но мне нужно это преобразование типовb, потому что во всем приложении я использую ISomeWrapper в качестве переменной, хранящей экземпляр SomeWrapper. (Кроме того, SomeWrapper - единственный класс, реализующий ISomeWrapper).

Есть ли способ сделать неявное преобразование, если интерфейс ISomeWrapper соответствует типу, который я знаю в моем конкретном классе?

Edit: Как предполагается всеми, неявное приведение из интерфейса невозможно в C #.

Почему мне нужно это сделать? Я хочу разрешить (неявно) пользователю ISomeWrapper вызывать методы, которые требуют ActualRec в качестве параметра БЕЗ предоставления доступа пользователям ISomeWrapper для вызова методов / свойств ActualRec.

Например, Если я включу свойство ActualRec в ISomeWrapper, то пользователи ISomeWrapper смогут вызывать методы, доступные в ActualRec (скажем, someWrapper.ActualRec.Dispose ()), которые я НЕ хочу раскрывать.

Вот причина попытки найти неявное преобразование.

Кроме того, я не хочу использовать SomeWrapper в приложении.

Пожалуйста, предложите, если есть какая-то концепция / шаблон для этого.

Спасибо за проявленный интерес.

Ответы [ 3 ]

6 голосов
/ 21 апреля 2011

Это ограничено в C #. Читайте ниже.

http://msdn.microsoft.com/en-us/library/aa664464%28VS.71%29.aspx

Классу или структуре разрешается объявлять преобразование из исходного типа S в целевой тип T при условии, что выполняются все следующие условия:

...

Ни S, ни T не являются объектами или интерфейсами.

Кроме того,

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

6 голосов
/ 21 апреля 2011

Я бы сказал, что в вашем дизайне есть недостаток.Вы переходите к конкретному типу из интерфейса, что делает использование интерфейса довольно бессмысленным.Интерфейс - это контракт, посредством которого реализуемые типы будут соответствовать предоставлению требуемого набора услуг.В вашем примере, свойство SomeInfo не определено в интерфейсе (контракт)?Если нет, то почему вы вообще пытаетесь кастовать, используя интерфейс?Вы должны использовать SomeWrapper в качестве самого входного аргумента.

2 голосов
/ 21 апреля 2011

C # не позволяет этого, потому что такая функция легко может привести к нечитаемому коду, который ослепит других разработчиков. Попробуйте вместо этого использовать метод расширения:

public static class SomeWrapperExtensions
{
    public static ActualRec ToActualRec(
        this ISomeWrapper wrapper)
    {
        return ((SomeWrapper)someWrapper).SomeInfo;
    }
}

Это позволяет вам выполнить соглашение таким образом, чтобы не удивило других разработчиков:

ActualRec rec = wrapper.ToActualRec();

Обратите внимание, что это все еще хрупко, потому что вы не знаете, представляет ли ISomeWrapper реализацию SomeWrapper.

...