Почему это неявное преобразование типов в C # терпит неудачу? - PullRequest
5 голосов
/ 26 марта 2010

Справочная информация:

Предположим, у меня есть следующий класс:

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 & rarr; Wrapped<T>. В конечном итоге я хотел бы иметь возможность использовать этот класс следующим образом:

interface IX  { /* ... */ }

class X : IX  { /* ... */ }

...

IX plainIX = new X();

using (Wrapped<IX> wrappedIX = plainIX)
{
    /* ... */
} 

Проблема:

Однако преобразование типов в приведенном выше предложении using завершается неудачно. Хотя я могу назначить new X() непосредственно для wrappedIX, мне не разрешено присваивать ему что-либо типа IX. Компилятор пожалуется на следующую ошибку:

Ошибка компилятора CS0266: Невозможно неявно преобразовать тип 'IX' в 'Wrapped '. Существует явное обращение (вам не хватает приведения?)

Я не понимаю этого. В чем здесь проблема?

1 Ответ

6 голосов
/ 26 марта 2010

Я считаю, что это потому, что 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))

По сути, преобразования могут быть немного сложными по разным причинам - простые методы, как правило, легче понять, ИМО.

...