摘要通用隐式转换为派生类型,错误?

时间:2014-12-14 22:36:46

标签: c# generics abstract implicit-conversion

假设抽象类型A的以下定义:

public abstract class A<T, J> : where J : A<T, J>, new()
{
    public virtual T Value { get; set; }

    //Error: User-defined conversion must convert to or from the enclosing type
    public static implicit operator J(T value)
    {
        return new J
        {
            Value = value
        };
    }
}

隐式运算符导致编译器发出错误“用户定义的转换必须转换为封闭类型或从封闭类型转换。”

隐式运算符转换为封闭类型的派生类型。这是C#的错误还是限制?

我正在尝试将T型拳击概括为J。

更新

继续该错误,我尝试了以下内容:

public abstract class A<T, J> : where J : Primary<T, J>, new()
{
    public virtual T Value { get; set; }

    public static implicit operator A<T, J>(T value)
    {
        return new J
        {
            Value = value
        };
    }

    public static implicit operator J(A<T, J> value)
    {
        return value as J;
    }
}

这确实可以防止编译器错误(如预期的那样),尽管它会强制显式转换。这是不可取的。

基本上,我希望能够做到以下几点:

public class B { }

public class C : A<B, C> 
{ 
    public C Foo(B b)
    {
        return b;
    }
}

上述任何其他替代方法,以提供类型的广义隐式装箱?

1 个答案:

答案 0 :(得分:3)

使您的班级A<T, J>能够正常工作的最接近的是:

public class A<T, J> where J : A<T, J>, new()
{
    public virtual T Value { get; set; }

    public static implicit operator A<T, J>(T value)
    {
        return new A<T, J>
        {
            Value = value
        };
    }
}

但是只要你标记abstract,它就会因为new A<T, J>而失败。因此,能够依靠where J : A<T, J>, new()来表示您正在创建派生类型是很好的。但那不再是有效的c#语法。

最重要的是,你不能做你希望做的隐式转换。

您可以进行显式转换:

public abstract class A<T, J> where J : A<T, J>, new()
{
    public virtual T Value { get; set; }

    public static J Convert(T value)
    {
        return new J
        {
            Value = value
        };
    }
}

现在这可行:

public class B { }

public class C : A<B, C> 
{ 
    public C Foo(B b)
    {
        return C.Convert(b);
    }
}

结果代码中的净差异非常小,但您必须进行显式转换(对于代码可读性和维护而言,这不是一件坏事。)