Почему C# не позволяет типам, использующим композицию, иметь неявные преобразования для интерфейсов? [дубликат]

Возможные Дубликаты:
почему я не могу использовать интерфейс с явной оператора?

когда я делаю это:

public struct Effect
{
    public IEffect IEffect { get; private set; }

    public Effect ( IEffect effect )
    {
        this.IEffect = effect;
    }

    public static implicit operator IEffect ( Effect effect )
    {
        return effect.IEffect;
    }

    public static explicit operator Effect ( IEffect effect )
    {
        return new Effect ( effect );
    }
}

Я получаю такую ошибку компилятора:

'.Эффект.неявный оператор Объекта imageeditor.Ieffect, Который(Объекта Imageeditor.Эффект'): пользовательские преобразования в или из интерфейс не разрешен.

почему они не пускают? Это не хорошо практика?

3 ответов


Это подробно описано в разделе 10.10.3 спецификации языка C#.

резюме причина почему хотя ...

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

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

IEffect anIEffectInstance = GetEffectAsInterface();

if(anIEffectInstance is Effect) //<--you cannot override this behavior to return true,
   var interfaceAscConcrete = (Effect)anIEffectInstance; //<-- so this overridden code would never execute

звучит как вопрос для Джона Скита или что-то в этом роде, но я все равно попытаюсь.

неявный оператор, который вы описали, в основном будет просто ненужным. Если Effect уже реализует IEffect, вы можете использовать Effect везде, где вам нужен объект, реализующий IEffect не беспокоясь о пользовательском преобразовании.

проблема явного оператора может быть немного более философской. Мое понимание заключается в том, что смысл имплицитного и явные преобразования-это преобразование объекта одного типа в объект другого типа, связь с которым по какой-то причине еще не очевидна компилятору. Однако интерфейс не является объектом. Невозможно создать экземпляр интерфейса напрямую; скорее, интерфейс должен быть реализован каким-то классом. При использовании неявных или явных преобразований результирующий объект не связан по типу с предыдущим объектом. Это означает, что объект, полученный в результате преобразования необходимо иметь возможность стоять независимо и иметь фактический тип объекта, которого сам по себе интерфейс не имеет.

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

если вы действительно должны сделать что-то подобное, вы хотели бы создать абстрактный базовый класс, который реализует интерфейс. Затем вы сможете "конвертировать" в и из абстрактный базовый класс, который имеет тип object.