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

时间:2019-03-21 08:13:53

标签: c# generics interface type-conversion covariance

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

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的{​​{1}}部分导致编译器产生以下错误:

  

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

我无法弄清楚问题出在哪里,因为转换的协方差似乎存在,甚至存在从FooContainer<T>定义的隐式转换。从T开始,我认为它应该像这样工作。

我想尽可能保持T : C的构造函数。

我希望有人可以为我指出这个问题的解决方案

1 个答案:

答案 0 :(得分:2)

  

甚至是从容器到T的隐式转换

是的,但这不是编译器所需要的。它要求:

  

隐式引用转换

(我的重点

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

editModalText() { let modalMessage="Hello, my name is /# Ann #/. I'm working for /# IStaff #/, could you please call me back" return ( <div> {modalMessage .split("/") .map((text, idx) => text.includes("#") ? this.replaceCharacter(idx, text) : text, )} </div> ) } replaceCharacter(idx, text) { let formattedText = text.replace(/#/g, " ") return ( <input key={idx} value={formattedText} onChange={e => this.setState({input:e.target.value})} /> ) } 具有 Container,并且可以通过用户定义的运算符转换为C,但这不足以使其成为 C。您的问题过于抽象,无法在此处说明解决方案-C应该是非通用的,并且是从Container派生的吗?这是“关闭”编译器的明显方法,但可能无法解决您的实际问题。

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


1 这些是埃里克·利珀特(Eric Lippert)的Representation-preserving conversions