Почему я не могу использовать "как" с параметром generic type, который ограничен интерфейсом?

В приведенном ниже примере (только для демонстрационной цели), если T не ограничен классом, то это преобразование:

var ret = objectA as T;

.. приведет к следующей ошибке компиляции:

Параметр типа 'T' не может использоваться с оператором 'as', потому что он не имеет ограничения типа класса или ограничения класса.

Я не понимаю, почему я не могу этого сделать. Поскольку я ограничил T интерфейсом IObject, компилятор должен знать, что T должен быть типом интерфейса, а операция as должна быть действительной.

public interface IObject
{
    string Id { get; set; }
}
public class ObjectA : IObject
{
    public string Id { get; set; }
}
public class ObjectFactory
{
    public T CreateObject<T>(string id) where T : IObject
    {
        ObjectA objectA = new ObjectA();
        var x = objectA as IObject; // this is good
        var ret = objectA as T; // why this 'as' cannot compile?
        return ret;
    }
    public T CreateClassObject<T>(string id) where T : class, IObject
    {
        ObjectA objectA = new ObjectA();
        var ret = objectA as T; // if T is class, this 'as' can compile
        return ret;
    }
}

Ответы

Ответ 1

так как я ограничил T интерфейсом IObject, компилятор должен знать, что T должен быть типом интерфейса, и операция "как" должна быть действительной.

Нет, T не обязательно должен быть тип интерфейса. Он должен быть типом, который реализует интерфейс. Рассмотрим:

public struct Foo : IObject
{
    public string Id { get; set; }
}

Теперь что бы вы ожидали сделать CreateObject<Foo>("ff")?

С ограничением class на CreateObject этот вызов недействителен, потому что Foo не является ссылочным типом - компилятор знает, что T является ссылочным типом, поэтому objectA as T в порядке.