当where约束应该足够时,为什么需要转换泛型类型

Mar*_*olo 1 c#

让我们从以下分类开始

public abstract class Automobile { }

public class Automobile<T> : Automobile where T : Automobile { }

public class Car : Automobile<Car> { }
public class Truck : Automobile<Truck> { }

public class SmartAutomobile<T> : Automobile<T>
{
    public T MyAutomobile { get; set; }

    public SmartAutomobile(SmartTechnology smart)
    {
        // Cannot implicitly convert Automobile to T
        this.MyAutomobile = AutomobileFromSmart(typeof(T), smart);
    }

    public static Automobile AutomobileFromSmart(Type type, SmartTechnology smart)
    {
        if (type == typeof(Car))
            return new Car { /* ... */ };
        else
            throw new NotImplementedException("Car type " + type.FullName + " not recognized");
    }
}

public class SmartTechnology  { }
Run Code Online (Sandbox Code Playgroud)

正如您从注释中看到的那样,编译器说它无法将an转换AutomobileTin SmartAutomobile<T>的构造函数.怎么会这样?编译器应该知道T,因为约束Automobile<T>,一个Automobile.

如果我试着明确地施展它

this.MyAutomobile = AutomobileFromSmart(typeof(T), smart) as T;
Run Code Online (Sandbox Code Playgroud)

我得到编译器错误

类型参数"T"不能与"as"运算符一起使用,因为它没有类类型约束,也没有"类"约束

现在,如果我也在中定义where约束SmartAutomobile<T>

public class SmartAutomobile<T> : Automobile<T> where T : Automobile
Run Code Online (Sandbox Code Playgroud)

编译器不显示任何错误

但是如果我删除了显式的强制转换:

this.MyAutomobile = AutomobileFromSmart(typeof(T), smart);
Run Code Online (Sandbox Code Playgroud)

无法隐式转换汽车与T错误再次出现.

怎么可能是编译器没有意识到where约束力T是一个Automobile

D S*_*ley 5

怎么可能是翻译没有意识到哪里约束迫使T成为汽车?

不,它迫使T衍生 Automobile.因为向下投射并不总是安全的,所以你不能暗中投射AutomobileT.如果TCar,但AutomobileFromSmart返回了a Truck,那么演员阵容将在运行时失败.你可以显式地(或使用as)告诉编译器"我知道我在做什么,这个演员在运行时是安全的").

  • 根据你现在所拥有的,是的,但是编译器并没有深入挖掘知道这一点.此外,该方法是"公共",因此无法保证其他人不会使用其他类型调用它. (2认同)