为什么我不能将泛型类型的一个实例化转换为另一个?

Vla*_*hek 20 c# generics struct casting

如何实现结构以便执行以下转换?

var a = new StatusedValue<double>(1, false);
var b = (StatusedValue<int>)a;
Run Code Online (Sandbox Code Playgroud)

我的实现应该表现得相似Nullable<T>,哪种方式正常.但是,此代码失败System.InvalidCastException:

public struct StatusedValue<T>  where T : struct
{
    public StatusedValue(T value) : this(value, true)
    {

    }

    public StatusedValue(T value, bool isValid)
    {
        this.value = value;
        this.isValid = isValid;
    }

    private T value;
    private bool isValid;

    public static implicit operator StatusedValue<T>(T value)
    {
        return new StatusedValue<T>(value);
    }

    public static explicit operator T(StatusedValue<T> value)
    {
        return value.value;
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

无法将"StatusedValue`1 [System.Double]"类型的对象强制转换为"StatusedValue`1 [System.Int32]".

dca*_*tro 17

这适用于Nullable<T>类型,因为它们从编译器获得特殊处理.这被称为"提升转换运算符",您无法定义自己的.

C#规范的 6.4.2节:

6.4.2提升转换运营商

给定一个用户定义的转换运算符,它从非可空值类型S转换为非可空值类型T,存在一个从S转换的提升转换运算符?到T?.这个提升的转换操作符执行从S解包?到S后跟用户定义的从S到T的转换,接着是从T到T的包装,除了空值S?直接转换为空值T?.提升转换运算符与其基础用户定义转换运算符具有相同的隐式或显式分类.术语"用户定义的转换"适用于用户定义和提升转换运算符的使用


Raw*_*ing 6

如果您对调用方法感到满意,请尝试

public StatusedValue<U> CastValue<U>() where U : struct
{
    return new StatusedValue<U>((U)Convert.ChangeType(value, typeof(U)), isValid);
}
Run Code Online (Sandbox Code Playgroud)

遗憾的是,如果无法转换为,则会在运行时而不是编译时抛出.TU

编辑:正如下面所指出的,如果你IConvertible和/而不是那样约束,struct那么理论上每次转换在编译时都是可能的,并且由于运行时值不正确,你只会遇到运行时故障.