Почему это неявное преобразование типов в C # завершается неудачей?
-
22-09-2019 - |
Вопрос
Предыстория:
Давайте предположим, что у меня есть следующий класс:
class Wrapped<T> : IDisposable
{
public Wrapped(T obj) { /* ... */ }
public static implicit operator Wrapped<T>(T obj)
{
return new Wrapped<T>(obj);
}
public void Dispose() { /* ... */ }
}
Как вы можете видеть, он предоставляет неявный оператор преобразования типа для T
→ Wrapped<T>
.В конечном счете, я хотел бы иметь возможность использовать этот класс следующим образом:
interface IX { /* ... */ }
class X : IX { /* ... */ }
...
IX plainIX = new X();
using (Wrapped<IX> wrappedIX = plainIX)
{
/* ... */
}
Проблема:
Однако преобразование типа в приведенном выше using
условие не выполняется.В то время как я могу назначить new X()
непосредственно к wrappedIX
, Мне не разрешено назначать что - либо типа IX
к этому.Компилятор выдаст следующую ошибку:
Ошибка компилятора CS0266:Не удается неявно преобразовать тип 'IX' в 'Завернутый<IX>'.Существует явная onversion (вам не хватает приведения?)
Я этого не понимаю.В чем здесь проблема?
Решение
Я верю, что это потому, что IX
это интерфейс.Компилятор считает, что, возможно, значение типа IX
уже может быть получен из Wrapped<IX>
(даже если Wrapped<T>
запечатан), поэтому он не использует преобразование.
Детали довольно сложны в разделах 6.4.3 и 6.4.4 спецификации C # 3.0.В основном потому, что IX
это интерфейс, он не "охвачен" никакими типами, что означает, что более поздний шаг в 6.4.4 завершается неудачей.
Я предлагаю вам создать не универсальный тип Wrapped
с помощью этого метода:
public static Wrapped<T> Of<T>(T item)
{
return new Wrapped<T>(item);
}
Тогда вы можете просто написать:
using (Wrapped<IX> wrappedIX = Wrapped.Of(plainIX))
В принципе, преобразования могут быть немного сложными по разным причинам - простые методы, как правило, легче понять, IMO.