“即使定义了转换,也没有隐式引用转换”

问题描述 投票:2回答:1

为了提供类型安全的接口,我编写了以下代码:

namespace MWE
{
    public abstract class C {}
    public class A : C {}
    public class B : C {}

    public class Container<T> where T : C
    {
        public readonly T Value;

        public static implicit operator T(Container<C> c)
        {
            return c.Value;
        }
    }

    public interface IWrapper<out TC> where TC : C {}

    public class Foo
    {
        public Foo(IWrapper<Container<C>> wrapper) {}
    }
}

不幸的是,这不编译。 Compiler<C>-wrapper构造函数的Foo参数部分会导致编译器产生以下错误:

类型'MFE.Container <MFE.C>'不能用作泛型类型或方法'IWrapper <TC>'中的类型参数'TC'。没有从'MFE.Container <MFE.C>'到'MFE.C'的隐式引用转换。 类型'MFE.Container <MFE.C>'必须可转换为'WeirdTestStuff.C',以便在通用接口'MFE.IWrapper <out TC>'中将其用作参数'TC'。

我无法确定问题的确切位置,因为转换的协方差似乎存在,甚至存在从Container<T>T定义的隐式转换。自从T : C以来,我认为它应该像这样工作。

如果可能的话,我想保持Foo的构造函数。

我希望有人能指出我解决这个问题

c# generics interface type-conversion covariance
1个回答
2
投票

甚至是从Container定义的隐式转换

这是事实,但这不是编译器所需要的。这个需要:

隐式引用转换

(我的重点)

隐式引用转换不是由任何用户定义的运算符提供的,只有当一个类型从另一个类型派生(直接或通过中间类型)时才允许。

Container有一个C,可以通过用户定义的运算符转换为C,但这还不足以使它成为C.你的问题太抽象了,无法说明修复应该在这里 - 如果Container是非泛型的并源自C?这是“闭嘴”编译器的明显方法,但可能无法解决您的实际问题。

您不能使用泛型来使类型的基类型在运行时可设置。


1这些是Eric Lippert的Representation-preserving conversions

© www.soinside.com 2019 - 2024. All rights reserved.