«нет неявного преобразования ссылок», даже если преобразование определено - PullRequest
2 голосов
/ 21 марта 2019

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

namespace MWE
{
    public abstract class C {}
    public class A : C {}
    public class B : C {}

    public class Container<T> where T : C
    {
        public readonly T Value;

        public static implicit operator T(Container<C> c)
        {
            return c.Value;
        }
    }

    public interface IWrapper<out TC> where TC : C {}

    public class Foo
    {
        public Foo(IWrapper<Container<C>> wrapper) {}
    }
}

К сожалению, это не компилируется. * Compiler<C> -часть параметра wrapper в конструкторе Foo заставляет компилятор выдавать следующую ошибку:

Тип «MFE.Container » нельзя использовать в качестве параметра типа «TC» в универсальном типе или методе «IWrapper ». Не существует неявного преобразования ссылок из 'MFE.Container ' в 'MFE.C'.
Тип «MFE.Container » должен быть преобразован в «WeirdTestStuff.C», чтобы использовать его в качестве параметра «TC» в универсальном интерфейсе «MFE.IWrapper ».

Я не могу понять, где именно проблема, поскольку ковариация для преобразования, кажется, существует, и даже существует неявное преобразование из Container<T> в T. Начиная с T : C, я предположил, что это должно просто так работать.

Я бы хотел сохранить конструктор Foo, как это возможно.

Надеюсь, кто-нибудь подскажет мне решение этой проблемы

1 Ответ

2 голосов
/ 21 марта 2019

даже неявное преобразование из Контейнера в определенное T

Это правда, но это не то, что требуется компилятору.Требуется:

неявное ссылка преобразование

(Мой выделение )

неявное преобразование ссылкине предоставляется ни одним пользовательским оператором и допускается только в том случае, если один тип наследует (напрямую или через промежуточные типы) от другого 1 .

Container has- C и может быть преобразован в C через пользовательский оператор, но этого недостаточно, чтобы сделать его be-a C. Ваш вопрос слишком абстрактен, чтобы сказать, что исправитьдолжен быть здесь - должен Container быть не универсальным и производным от C?Это очевидный способ «заткнуть» компилятор, но он может не решить вашу реальную проблему.

Вы не можете использовать универсальные шаблоны для установки базового типа типа во время выполнения.


1 Это преобразования Эрика Липперта , сохраняющие представление

...